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

Diff of /xvidcore/src/plugins/plugin_lumimasking.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.2.1, Sun Mar 16 12:05:09 2003 UTC revision 1.1.2.5, Thu Oct 2 13:54:27 2003 UTC
# Line 1  Line 1 
1    /*****************************************************************************
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     *
9     *  This program is free software ; you can redistribute it and/or modify
10     *  it under the terms of the GNU General Public License as published by
11     *  the Free Software Foundation ; either version 2 of the License, or
12     *  (at your option) any later version.
13     *
14     *  This program is distributed in the hope that it will be useful,
15     *  but WITHOUT ANY WARRANTY ; without even the implied warranty of
16     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     *  GNU General Public License for more details.
18     *
19     *  You should have received a copy of the GNU General Public License
20     *  along with this program ; if not, write to the Free Software
21     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22     *
23     * $Id$
24     *
25     ****************************************************************************/
26    
27    #include <stdlib.h>
28    
29  #include "../xvid.h"  #include "../xvid.h"
30  #include "../image/image.h"  #include "../portab.h"
31  #include "../quant/adapt_quant.h"  
32    /*****************************************************************************
33     * Private data type
34     ****************************************************************************/
35    
36  int xvid_plugin_lumimasking(void * handle, int opt, void * param1, void * param2)  typedef struct
37  {  {
38      switch(opt)          float *quant;
39            float *val;
40    } lumi_data_t;
41    
42    /*****************************************************************************
43     * Sub plugin functions
44     ****************************************************************************/
45    
46    static int lumi_plg_info(xvid_plg_info_t *info);
47    static int lumi_plg_create(xvid_plg_create_t *create, lumi_data_t **handle);
48    static int lumi_plg_destroy(lumi_data_t *handle, xvid_plg_destroy_t * destroy);
49    static int lumi_plg_before(lumi_data_t *handle, xvid_plg_data_t *data);
50    static int lumi_plg_after(lumi_data_t *handle, xvid_plg_data_t *data);
51    
52    /*****************************************************************************
53     * The plugin entry function
54     ****************************************************************************/
55    
56    int
57    xvid_plugin_lumimasking(void * handle, int opt, void * param1, void * param2)
58      {      {
59            switch(opt) {
60      case XVID_PLG_INFO :      case XVID_PLG_INFO :
61                    return(lumi_plg_info((xvid_plg_info_t*)param1));
62            case XVID_PLG_CREATE:
63                    return(lumi_plg_create((xvid_plg_create_t *)param1, (lumi_data_t **)param2));
64            case XVID_PLG_DESTROY:
65                    return(lumi_plg_destroy((lumi_data_t *)handle, (xvid_plg_destroy_t*)param1));
66            case XVID_PLG_BEFORE :
67                    return(lumi_plg_before((lumi_data_t *)handle, (xvid_plg_data_t *)param1));
68            case XVID_PLG_AFTER :
69                    return(lumi_plg_after((lumi_data_t *)handle, (xvid_plg_data_t *)param1));
70            }
71    
72            return(XVID_ERR_FAIL);
73    }
74    
75    /*----------------------------------------------------------------------------
76     * Info plugin function
77     *--------------------------------------------------------------------------*/
78    
79    static int
80    lumi_plg_info(xvid_plg_info_t *info)
81          {          {
82          xvid_plg_info_t * info = (xvid_plg_info_t*)param1;          /* We just require a diff quant array access */
83          info->flags = XVID_REQDQUANTS;          info->flags = XVID_REQDQUANTS;
84          return 0;          return(0);
85          }          }
86    
87      case XVID_PLG_CREATE :  /*----------------------------------------------------------------------------
88      case XVID_PLG_DESTROY :   * Create plugin function
89          return 0;   *
90     * Allocates the private plugin data arrays
91     *--------------------------------------------------------------------------*/
92    
93    static int
94    lumi_plg_create(xvid_plg_create_t *create, lumi_data_t **handle)
95    {
96            lumi_data_t *lumi;
97    
98      case XVID_PLG_BEFORE :          if ((lumi = (lumi_data_t*)malloc(sizeof(lumi_data_t))) == NULL)
99                    return(XVID_ERR_MEMORY);
100    
101            lumi->quant = (float*)malloc(create->mb_width*create->mb_height*sizeof(float));
102            if (lumi->quant == NULL) {
103                    free(lumi);
104                    return(XVID_ERR_MEMORY);
105            }
106    
107            lumi->val = (float*)malloc(create->mb_width*create->mb_height*sizeof(float));
108            if (lumi->val == NULL) {
109                    free(lumi->quant);
110                    free(lumi);
111                    return(XVID_ERR_MEMORY);
112            }
113    
114            /* Bind the data structure to the handle */
115            *handle = lumi;
116    
117            return(0);
118    }
119    
120    /*----------------------------------------------------------------------------
121     * Destroy plugin function
122     *
123     * Free the private plugin data arrays
124     *--------------------------------------------------------------------------*/
125    
126    static int
127    lumi_plg_destroy(lumi_data_t *handle, xvid_plg_destroy_t *destroy)
128          {          {
129          xvid_plg_data_t * data = (xvid_plg_data_t*)param1;          if (handle) {
130               data->quant =                  if (handle->quant) {
131                      adaptive_quantization(data->current.plane[0], data->current.stride[0],                          free(handle->quant);
132                                            data->dquant,                          handle->quant = NULL;
133                                    data->quant /* framequant*/,                  }
134                                    data->quant /* min_quant */,                  if (handle->val) {
135                                                            data->quant*2 /* max_quant */,                          free(handle->val);
136                                                            data->mb_width, data->mb_height);                          handle->val = NULL;
137                    }
138                    free(handle);
139            }
140            return(0);
141    }
142    
143    /*----------------------------------------------------------------------------
144     * Before plugin function
145     *
146     * Here is all the magic about lumimasking.
147     *--------------------------------------------------------------------------*/
148    
149    /* Helper function defined later */
150    static int normalize_quantizer_field(float *in,
151                                                                             int *out,
152                                                                             int num,
153                                                                             int min_quant,
154                                                                             int max_quant);
155    
156    static int
157    lumi_plg_before(lumi_data_t *handle, xvid_plg_data_t *data)
158    {
159            int i, j;
160    
161            float global = 0.0f;
162            uint32_t mid_range = 0;
163    
164            const float DarkAmpl = 14 / 2;
165            const float BrightAmpl = 10 / 2;
166            const float DarkThres = 70;
167            const float BrightThres = 200;
168    
169            const float GlobalDarkThres = 60;
170            const float GlobalBrightThres = 170;
171    
172            const float MidRangeThres = 20;
173            const float UpperLimit = 200;
174            const float LowerLimit = 25;
175    
176            /* Do this for all macroblocks individually  */
177            for (j = 0; j < data->mb_height; j++) {
178                    for (i = 0; i < data->mb_width; i++) {
179                            int k, l;
180                            unsigned char *ptr;
181    
182                            /* Initialize the current quant value to the frame quant */
183                            handle->quant[j*data->mb_width + i] = (float)data->quant;
184    
185                            /* Reset the val value */
186                            handle->val[j*data->mb_width + i] = 0.0f;
187    
188                            /* Next steps compute the luminance-masking */
189    
190          return 0;                          /* Get the MB address */
191                            ptr  = data->current.plane[0];
192                            ptr += 16*j*data->current.stride[0] + 16*i;
193    
194                            /* Accumulate luminance */
195                            for (k = 0; k < 16; k++)
196                                    for (l = 0; l < 16; l++)
197                                            handle->val[j*data->mb_width + i] += ptr[k*data->current.stride[0] + l];
198    
199                            /* Normalize its value */
200                            handle->val[j*data->mb_width + i] /= 256.0f;
201    
202                            /* Accumulate the global frame luminance */
203                            global += handle->val[j*data->mb_width + i];
204    
205                            /* Count the number of middle luminance blocks */
206                            if ((handle->val[j*data->mb_width + i] > LowerLimit) &&
207                                    (handle->val[j*data->mb_width + i] < UpperLimit))
208                                    mid_range++;
209                    }
210         }         }
211    
212      case XVID_PLG_AFTER :          /* Normalize the global luminance accumulator */
213         return 0;          global /= data->mb_width*data->mb_height;
214    
215            /* Apply luminance masking only to frames where the global luminance is
216             * higher than DarkThreshold and lower than Bright Threshold, or where
217             * "middle" luminance blocks are lower than its corresponding threshold */
218             if (((global < GlobalBrightThres) && (global > GlobalDarkThres)) ||
219                    (mid_range < MidRangeThres)) {
220    
221                    /* Apply the luminance masking formulas to all MBs */
222                    for (i = 0; i < data->mb_height; i++) {
223                            for (j = 0; j < data->mb_width; j++) {
224                                    if (handle->val[i*data->mb_width + j] < DarkThres)
225                                            handle->quant[i*data->mb_width + j] += DarkAmpl * (DarkThres - handle->val[i*data->mb_width + j]) / DarkThres;
226                                    else if (handle->val[i*data->mb_width + j] > BrightThres)
227                                            handle->quant[i*data->mb_width + j] += BrightAmpl * (handle->val[i*data->mb_width + j] - BrightThres) / (255 - BrightThres);
228                            }
229      }      }
230            }
231    
232             /* Normalize the quantizer field */
233             data->quant = normalize_quantizer_field(handle->quant,
234                                                                                             data->dquant,
235                                                                                             data->mb_width*data->mb_height,
236                                                                                             data->quant,
237                                                                                             data->quant*2);
238    
239             /* Plugin job finished */
240             return(0);
241    }
242    
243    /*----------------------------------------------------------------------------
244     * After plugin function (dummy function)
245     *--------------------------------------------------------------------------*/
246    
247      return XVID_ERR_FAIL;  static int
248    lumi_plg_after(lumi_data_t *handle, xvid_plg_data_t *data)
249    {
250            return(0);
251  }  }
252    
253    /*****************************************************************************
254     * Helper functions
255     ****************************************************************************/
256    
257    #define RDIFF(a, b)    ((int)(a+0.5)-(int)(b+0.5))
258    
259    static int
260    normalize_quantizer_field(float *in,
261                                                      int *out,
262                                                      int num,
263                                                      int min_quant,
264                                                      int max_quant)
265    {
266            int i;
267            int finished;
268    
269            do {
270                    finished = 1;
271                    for (i = 1; i < num; i++) {
272                            if (RDIFF(in[i], in[i - 1]) > 2) {
273                                    in[i] -= (float) 0.5;
274                                    finished = 0;
275                            } else if (RDIFF(in[i], in[i - 1]) < -2) {
276                                    in[i - 1] -= (float) 0.5;
277                                    finished = 0;
278                            }
279    
280                            if (in[i] > max_quant) {
281                                    in[i] = (float) max_quant;
282                                    finished = 0;
283                            }
284                            if (in[i] < min_quant) {
285                                    in[i] = (float) min_quant;
286                                    finished = 0;
287                            }
288                            if (in[i - 1] > max_quant) {
289                                    in[i - 1] = (float) max_quant;
290                                    finished = 0;
291                            }
292                            if (in[i - 1] < min_quant) {
293                                    in[i - 1] = (float) min_quant;
294                                    finished = 0;
295                            }
296                    }
297            } while (!finished);
298    
299            out[0] = 0;
300            for (i = 1; i < num; i++)
301                    out[i] = RDIFF(in[i], in[i - 1]);
302    
303            return (int) (in[0] + 0.5);
304    }

Legend:
Removed from v.1.1.2.1  
changed lines
  Added in v.1.1.2.5

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