[svn] / trunk / xvidcore / src / plugins / plugin_lumimasking.c Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/src/plugins/plugin_lumimasking.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1873 - (view) (download)

1 : edgomez 1382 /*****************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC
4 :     * - XviD plugin: performs a lumimasking algorithm on encoded frame -
5 :     *
6 :     * Copyright(C) 2002-2003 Peter Ross <pross@xvid.org>
7 :     * 2002 Christoph Lampert <gruel@web.de>
8 : Isibaar 1863 * 2008 Jason Garrett-Glaser <darkshikari@gmail.com>
9 : edgomez 1382 *
10 :     * This program is free software ; you can redistribute it and/or modify
11 :     * it under the terms of the GNU General Public License as published by
12 :     * the Free Software Foundation ; either version 2 of the License, or
13 :     * (at your option) any later version.
14 :     *
15 :     * This program is distributed in the hope that it will be useful,
16 :     * but WITHOUT ANY WARRANTY ; without even the implied warranty of
17 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 :     * GNU General Public License for more details.
19 :     *
20 :     * You should have received a copy of the GNU General Public License
21 :     * along with this program ; if not, write to the Free Software
22 :     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 :     *
24 : Isibaar 1873 * $Id: plugin_lumimasking.c,v 1.8 2009-06-02 13:06:54 Isibaar Exp $
25 : edgomez 1382 *
26 :     ****************************************************************************/
27 :    
28 :     #include <stdlib.h>
29 : Isibaar 1863 #include <stdio.h>
30 :     #include <math.h>
31 : edgomez 1382
32 :     #include "../xvid.h"
33 : syskin 1704 #include "../global.h"
34 : edgomez 1382 #include "../portab.h"
35 :     #include "../utils/emms.h"
36 :    
37 :     /*****************************************************************************
38 :     * Private data type
39 :     ****************************************************************************/
40 :    
41 :     typedef struct
42 :     {
43 :     float *quant;
44 :     float *val;
45 : Isibaar 1863 int method;
46 : edgomez 1382 } lumi_data_t;
47 :    
48 :     /*****************************************************************************
49 :     * Sub plugin functions
50 :     ****************************************************************************/
51 :    
52 :     static int lumi_plg_info(xvid_plg_info_t *info);
53 :     static int lumi_plg_create(xvid_plg_create_t *create, lumi_data_t **handle);
54 :     static int lumi_plg_destroy(lumi_data_t *handle, xvid_plg_destroy_t * destroy);
55 :     static int lumi_plg_frame(lumi_data_t *handle, xvid_plg_data_t *data);
56 :     static int lumi_plg_after(lumi_data_t *handle, xvid_plg_data_t *data);
57 :    
58 :     /*****************************************************************************
59 :     * The plugin entry function
60 :     ****************************************************************************/
61 :    
62 :     int
63 :     xvid_plugin_lumimasking(void * handle, int opt, void * param1, void * param2)
64 :     {
65 :     switch(opt) {
66 :     case XVID_PLG_INFO:
67 :     return(lumi_plg_info((xvid_plg_info_t*)param1));
68 :     case XVID_PLG_CREATE:
69 :     return(lumi_plg_create((xvid_plg_create_t *)param1, (lumi_data_t **)param2));
70 :     case XVID_PLG_DESTROY:
71 :     return(lumi_plg_destroy((lumi_data_t *)handle, (xvid_plg_destroy_t*)param1));
72 :     case XVID_PLG_BEFORE :
73 :     return 0;
74 :     case XVID_PLG_FRAME :
75 :     return(lumi_plg_frame((lumi_data_t *)handle, (xvid_plg_data_t *)param1));
76 :     case XVID_PLG_AFTER :
77 :     return(lumi_plg_after((lumi_data_t *)handle, (xvid_plg_data_t *)param1));
78 :     }
79 :    
80 :     return(XVID_ERR_FAIL);
81 :     }
82 :    
83 :     /*----------------------------------------------------------------------------
84 :     * Info plugin function
85 :     *--------------------------------------------------------------------------*/
86 :    
87 :     static int
88 :     lumi_plg_info(xvid_plg_info_t *info)
89 :     {
90 :     /* We just require a diff quant array access */
91 :     info->flags = XVID_REQDQUANTS;
92 :     return(0);
93 :     }
94 :    
95 :     /*----------------------------------------------------------------------------
96 :     * Create plugin function
97 :     *
98 :     * Allocates the private plugin data arrays
99 :     *--------------------------------------------------------------------------*/
100 :    
101 :     static int
102 :     lumi_plg_create(xvid_plg_create_t *create, lumi_data_t **handle)
103 :     {
104 :     lumi_data_t *lumi;
105 : Isibaar 1863 xvid_plugin_lumimasking_t *param = (xvid_plugin_lumimasking_t *) create->param;
106 : edgomez 1382
107 :     if ((lumi = (lumi_data_t*)malloc(sizeof(lumi_data_t))) == NULL)
108 :     return(XVID_ERR_MEMORY);
109 :    
110 : Isibaar 1863 lumi->method = 0;
111 : edgomez 1382 lumi->quant = (float*)malloc(create->mb_width*create->mb_height*sizeof(float));
112 :     if (lumi->quant == NULL) {
113 :     free(lumi);
114 :     return(XVID_ERR_MEMORY);
115 :     }
116 :    
117 :     lumi->val = (float*)malloc(create->mb_width*create->mb_height*sizeof(float));
118 :     if (lumi->val == NULL) {
119 :     free(lumi->quant);
120 :     free(lumi);
121 :     return(XVID_ERR_MEMORY);
122 :     }
123 :    
124 : Isibaar 1863 if (param != NULL)
125 :     lumi->method = param->method;
126 :    
127 : edgomez 1382 /* Bind the data structure to the handle */
128 :     *handle = lumi;
129 :    
130 :     return(0);
131 :     }
132 :    
133 :     /*----------------------------------------------------------------------------
134 :     * Destroy plugin function
135 :     *
136 :     * Free the private plugin data arrays
137 :     *--------------------------------------------------------------------------*/
138 :    
139 :     static int
140 :     lumi_plg_destroy(lumi_data_t *handle, xvid_plg_destroy_t *destroy)
141 :     {
142 :     if (handle) {
143 :     if (handle->quant) {
144 :     free(handle->quant);
145 :     handle->quant = NULL;
146 :     }
147 :     if (handle->val) {
148 :     free(handle->val);
149 :     handle->val = NULL;
150 :     }
151 :     free(handle);
152 :     }
153 :     return(0);
154 :     }
155 :    
156 :     /*----------------------------------------------------------------------------
157 :     * Before plugin function
158 :     *
159 :     * Here is all the magic about lumimasking.
160 :     *--------------------------------------------------------------------------*/
161 :    
162 :     /* Helper function defined later */
163 :     static int normalize_quantizer_field(float *in,
164 :     int *out,
165 :     int num,
166 :     int min_quant,
167 :     int max_quant);
168 :    
169 :     static int
170 :     lumi_plg_frame(lumi_data_t *handle, xvid_plg_data_t *data)
171 :     {
172 :     int i, j;
173 :    
174 :     float global = 0.0f;
175 :    
176 :     const float DarkAmpl = 14 / 4;
177 :     const float BrightAmpl = 10 / 3;
178 :     float DarkThres = 90;
179 :     float BrightThres = 200;
180 :    
181 :     const float GlobalDarkThres = 60;
182 :     const float GlobalBrightThres = 170;
183 :    
184 : Isibaar 1863 /* Arbitrary centerpoint for variance-based AQ. Roughly the same as used in x264. */
185 :     float center = 14000.f;
186 :     /* Arbitrary strength for variance-based AQ. */
187 :     float strength = 0.2f;
188 :    
189 : edgomez 1382 if (data->type == XVID_TYPE_BVOP) return 0;
190 :    
191 :     /* Do this for all macroblocks individually */
192 :     for (j = 0; j < data->mb_height; j++) {
193 :     for (i = 0; i < data->mb_width; i++) {
194 : Isibaar 1863 int k, l, sum = 0, sum_of_squares = 0;
195 : edgomez 1382 unsigned char *ptr;
196 :    
197 :     /* Initialize the current quant value to the frame quant */
198 :     handle->quant[j*data->mb_width + i] = (float)data->quant;
199 :    
200 :     /* Next steps compute the luminance-masking */
201 :    
202 :     /* Get the MB address */
203 :     ptr = data->current.plane[0];
204 :     ptr += 16*j*data->current.stride[0] + 16*i;
205 :    
206 : Isibaar 1863 if (handle->method) { /* Variance masking mode */
207 : Isibaar 1873 int variance = 0;
208 : Isibaar 1863 /* Accumulate sum and sum of squares over the MB */
209 :     for (k = 0; k < 16; k++) {
210 :     for (l = 0; l < 16; l++) {
211 :     int val = ptr[k*data->current.stride[0] + l];
212 :     sum += val;
213 :     sum_of_squares += val * val;
214 :     }
215 :     }
216 :     /* Variance = SSD - SAD^2 / (numpixels) */
217 : Isibaar 1873 variance = sum_of_squares - sum * sum / 256;
218 : Isibaar 1863 handle->val[j*data->mb_width + i] = (float)variance;
219 :     }
220 :     else { /* Luminance masking mode */
221 :     /* Accumulate luminance */
222 :     for (k = 0; k < 16; k++)
223 :     for (l = 0; l < 16; l++)
224 :     sum += ptr[k*data->current.stride[0] + l];
225 : edgomez 1382
226 : Isibaar 1863 handle->val[j*data->mb_width + i] = (float)sum/256.0f;
227 : edgomez 1382
228 : Isibaar 1863 /* Accumulate the global frame luminance */
229 :     global += (float)sum/256.0f;
230 :     }
231 : edgomez 1382 }
232 :     }
233 :    
234 : Isibaar 1863 if (handle->method) { /* Variance masking */
235 :     /* Apply the variance masking formula to all MBs */
236 :     for (i = 0; i < data->mb_height; i++)
237 :     {
238 :     for (j = 0; j < data->mb_width; j++)
239 :     {
240 :     float value = handle->val[i*data->mb_width + j];
241 :     float qscale_diff = strength * logf(value / center);
242 :     handle->quant[i*data->mb_width + j] *= (1.0f + qscale_diff);
243 :     }
244 :     }
245 :     }
246 :     else { /* Luminance masking */
247 :     /* Normalize the global luminance accumulator */
248 :     global /= data->mb_width*data->mb_height;
249 : edgomez 1382
250 : Isibaar 1863 DarkThres = DarkThres*global/127.0f;
251 :     BrightThres = BrightThres*global/127.0f;
252 : edgomez 1382
253 :    
254 : Isibaar 1863 /* Apply luminance masking only to frames where the global luminance is
255 :     * higher than DarkThreshold and lower than Bright Threshold */
256 :     if ((global < GlobalBrightThres) && (global > GlobalDarkThres)) {
257 : edgomez 1382
258 : Isibaar 1863 /* Apply the luminance masking formulas to all MBs */
259 :     for (i = 0; i < data->mb_height; i++) {
260 :     for (j = 0; j < data->mb_width; j++) {
261 :     if (handle->val[i*data->mb_width + j] < DarkThres)
262 :     handle->quant[i*data->mb_width + j] *= 1 + DarkAmpl * (DarkThres - handle->val[i*data->mb_width + j]) / DarkThres;
263 :     else if (handle->val[i*data->mb_width + j] > BrightThres)
264 :     handle->quant[i*data->mb_width + j] *= 1 + BrightAmpl * (handle->val[i*data->mb_width + j] - BrightThres) / (255 - BrightThres);
265 :     }
266 : edgomez 1382 }
267 :     }
268 :     }
269 :    
270 : Isibaar 1863 /* Normalize the quantizer field */
271 :     data->quant = normalize_quantizer_field(handle->quant,
272 : edgomez 1382 data->dquant,
273 :     data->mb_width*data->mb_height,
274 :     data->quant,
275 : syskin 1700 MAX(2,data->quant + data->quant/2));
276 : edgomez 1382
277 : Isibaar 1863 /* Plugin job finished */
278 :     return(0);
279 : edgomez 1382 }
280 :    
281 :     /*----------------------------------------------------------------------------
282 :     * After plugin function (dummy function)
283 :     *--------------------------------------------------------------------------*/
284 :    
285 :     static int
286 :     lumi_plg_after(lumi_data_t *handle, xvid_plg_data_t *data)
287 :     {
288 :     return(0);
289 :     }
290 :    
291 :     /*****************************************************************************
292 :     * Helper functions
293 :     ****************************************************************************/
294 :    
295 :     #define RDIFF(a, b) ((int)(a+0.5)-(int)(b+0.5))
296 :    
297 :     static int
298 :     normalize_quantizer_field(float *in,
299 :     int *out,
300 :     int num,
301 :     int min_quant,
302 :     int max_quant)
303 :     {
304 :     int i;
305 :     int finished;
306 :    
307 :     do {
308 :     finished = 1;
309 :     for (i = 1; i < num; i++) {
310 :     if (RDIFF(in[i], in[i - 1]) > 2) {
311 :     in[i] -= (float) 0.5;
312 :     finished = 0;
313 :     } else if (RDIFF(in[i], in[i - 1]) < -2) {
314 :     in[i - 1] -= (float) 0.5;
315 :     finished = 0;
316 :     }
317 :    
318 :     if (in[i] > max_quant) {
319 :     in[i] = (float) max_quant;
320 :     finished = 0;
321 :     }
322 :     if (in[i] < min_quant) {
323 :     in[i] = (float) min_quant;
324 :     finished = 0;
325 :     }
326 :     if (in[i - 1] > max_quant) {
327 :     in[i - 1] = (float) max_quant;
328 :     finished = 0;
329 :     }
330 :     if (in[i - 1] < min_quant) {
331 :     in[i - 1] = (float) min_quant;
332 :     finished = 0;
333 :     }
334 :     }
335 :     } while (!finished);
336 :    
337 :     out[0] = 0;
338 :     for (i = 1; i < num; i++)
339 :     out[i] = RDIFF(in[i], in[i - 1]);
340 :    
341 :     return (int) (in[0] + 0.5);
342 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4