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****************************************************************************/
37extern void vp8_get_processor_flags(int *mmx_enabled, int *xmm_enabled, int *wmt_enabled);
38
39/****************************************************************************
40*  Exported Global Variables
41****************************************************************************/
42void (*temp_filter)(pre_proc_instance *ppi, unsigned char *s, unsigned char *d, int bytes, int strength);
43void temp_filter_mmx
44(
45    pre_proc_instance *ppi,
46    unsigned char *s,
47    unsigned char *d,
48    int bytes,
49    int strength
50);
51void 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 ****************************************************************************/
79void 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 ****************************************************************************/
177void 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 ****************************************************************************/
208int 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