Home | History | Annotate | Download | only in encoder
      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 
     12 /****************************************************************************
     13 *
     14 *   Module Title :     preproc.c
     15 *
     16 *   Description  :     Simple pre-processor.
     17 *
     18 ****************************************************************************/
     19 
     20 /****************************************************************************
     21 *  Header Files
     22 ****************************************************************************/
     23 
     24 #include "memory.h"
     25 #include "preproc7.h"
     26 #include "vpx_mem/vpx_mem.h"
     27 
     28 /****************************************************************************
     29 *  Macros
     30 ****************************************************************************/
     31 #define FRAMECOUNT 7
     32 #define ROUNDUP32(X) ( ( ( (unsigned long) X ) + 31 )&( 0xFFFFFFE0 ) )
     33 
     34 /****************************************************************************
     35 *  Imports
     36 ****************************************************************************/
     37 extern void vp8_get_processor_flags(int *mmx_enabled, int *xmm_enabled, int *wmt_enabled);
     38 
     39 /****************************************************************************
     40 *  Exported Global Variables
     41 ****************************************************************************/
     42 void (*temp_filter)(pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int bytes, int strength);
     43 void temp_filter_mmx
     44 (
     45     pre_proc_instance *ppi,
     46     unsigned char *s,
     47     unsigned char *d,
     48     int bytes,
     49     int strength
     50 );
     51 void temp_filter_wmt
     52 (
     53     pre_proc_instance *ppi,
     54     unsigned char *s,
     55     unsigned char *d,
     56     int bytes,
     57     int strength
     58 );
     59 
     60 /****************************************************************************
     61  *
     62  *  ROUTINE       : temp_filter_c
     63  *
     64  *  INPUTS        : pre_proc_instance *ppi : Pointer to pre-processor instance.
     65  *                  unsigned char *s     : Pointer to source frame.
     66  *                  unsigned char *d     : Pointer to destination frame.
     67  *                  int bytes            : Number of bytes to filter.
     68  *                  int strength         : Strength of filter to apply.
     69  *
     70  *  OUTPUTS       : None.
     71  *
     72  *  RETURNS       : void
     73  *
     74  *  FUNCTION      : Performs a closesness adjusted temporarl blur
     75  *
     76  *  SPECIAL NOTES : Destination frame can be same as source frame.
     77  *
     78  ****************************************************************************/
     79 void temp_filter_c
     80 (
     81     pre_proc_instance *ppi,
     82     unsigned char *s,
     83     unsigned char *d,
     84     int bytes,
     85     int strength
     86 )
     87 {
     88     int byte = 0;
     89     unsigned char *frameptr = ppi->frame_buffer;
     90 
     91     if (ppi->frame == 0)
     92     {
     93         do
     94         {
     95             int frame = 0;
     96 
     97             do
     98             {
     99                 *frameptr = s[byte];
    100                 ++frameptr;
    101                 ++frame;
    102             }
    103             while (frame < FRAMECOUNT);
    104 
    105             d[byte] = s[byte];
    106 
    107             ++byte;
    108         }
    109         while (byte < bytes);
    110     }
    111     else
    112     {
    113         int modifier;
    114         int offset = (ppi->frame % FRAMECOUNT);
    115 
    116         do
    117         {
    118             int accumulator = 0;
    119             int count = 0;
    120             int frame = 0;
    121 
    122             frameptr[offset] = s[byte];
    123 
    124             do
    125             {
    126                 int pixel_value = *frameptr;
    127 
    128                 modifier   = s[byte];
    129                 modifier  -= pixel_value;
    130                 modifier  *= modifier;
    131                 modifier >>= strength;
    132                 modifier  *= 3;
    133 
    134                 if (modifier > 16)
    135                     modifier = 16;
    136 
    137                 modifier = 16 - modifier;
    138 
    139                 accumulator += modifier * pixel_value;
    140 
    141                 count += modifier;
    142 
    143                 frameptr++;
    144 
    145                 ++frame;
    146             }
    147             while (frame < FRAMECOUNT);
    148 
    149             accumulator += (count >> 1);
    150             accumulator *= ppi->fixed_divide[count];
    151             accumulator >>= 16;
    152 
    153             d[byte] = accumulator;
    154 
    155             ++byte;
    156         }
    157         while (byte < bytes);
    158     }
    159 
    160     ++ppi->frame;
    161 }
    162 /****************************************************************************
    163  *
    164  *  ROUTINE       : delete_pre_proc
    165  *
    166  *  INPUTS        : pre_proc_instance *ppi : Pointer to pre-processor instance.
    167  *
    168  *  OUTPUTS       : None.
    169  *
    170  *  RETURNS       : void
    171  *
    172  *  FUNCTION      : Deletes a pre-processing instance.
    173  *
    174  *  SPECIAL NOTES : None.
    175  *
    176  ****************************************************************************/
    177 void delete_pre_proc(pre_proc_instance *ppi)
    178 {
    179     if (ppi->frame_buffer_alloc)
    180         vpx_free(ppi->frame_buffer_alloc);
    181 
    182     ppi->frame_buffer_alloc = 0;
    183     ppi->frame_buffer      = 0;
    184 
    185     if (ppi->fixed_divide_alloc)
    186         vpx_free(ppi->fixed_divide_alloc);
    187 
    188     ppi->fixed_divide_alloc = 0;
    189     ppi->fixed_divide      = 0;
    190 }
    191 
    192 /****************************************************************************
    193  *
    194  *  ROUTINE       : init_pre_proc
    195  *
    196  *  INPUTS        : pre_proc_instance *ppi : Pointer to pre-processor instance.
    197  *                  int frame_size        : Number of bytes in one frame.
    198  *
    199  *  OUTPUTS       : None.
    200  *
    201  *  RETURNS       : int: 1 if successful, 0 if failed.
    202  *
    203  *  FUNCTION      : Initializes prepprocessor instance.
    204  *
    205  *  SPECIAL NOTES : None.
    206  *
    207  ****************************************************************************/
    208 int init_pre_proc7(pre_proc_instance *ppi, int frame_size)
    209 {
    210     int i;
    211     int mmx_enabled;
    212     int xmm_enabled;
    213     int wmt_enabled;
    214 
    215     vp8_get_processor_flags(&mmx_enabled, &xmm_enabled, &wmt_enabled);
    216 
    217     if (wmt_enabled)
    218         temp_filter = temp_filter_wmt;
    219     else if (mmx_enabled)
    220         temp_filter = temp_filter_mmx;
    221     else
    222         temp_filter = temp_filter_c;
    223 
    224 
    225     delete_pre_proc(ppi);
    226 
    227     ppi->frame_buffer_alloc = vpx_malloc(32 + frame_size * FRAMECOUNT * sizeof(unsigned char));
    228 
    229     if (!ppi->frame_buffer_alloc)
    230     {
    231         delete_pre_proc(ppi);
    232         return 0;
    233     }
    234 
    235     ppi->frame_buffer = (unsigned char *) ROUNDUP32(ppi->frame_buffer_alloc);
    236 
    237     ppi->fixed_divide_alloc = vpx_malloc(32 + 255 * sizeof(unsigned int));
    238 
    239     if (!ppi->fixed_divide_alloc)
    240     {
    241         delete_pre_proc(ppi);
    242         return 0;
    243     }
    244 
    245     ppi->fixed_divide = (unsigned int *) ROUNDUP32(ppi->fixed_divide_alloc);
    246 
    247     for (i = 1; i < 255; i++)
    248         ppi->fixed_divide[i] = 0x10000 / i;
    249 
    250     return 1;
    251 }
    252