[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.4, Thu Sep 11 12:58:37 2003 UTC revision 1.8, Tue Jun 2 13:06:54 2009 UTC
# Line 5  Line 5 
5   *   *
6   *  Copyright(C) 2002-2003 Peter Ross <pross@xvid.org>   *  Copyright(C) 2002-2003 Peter Ross <pross@xvid.org>
7   *               2002      Christoph Lampert <gruel@web.de>   *               2002      Christoph Lampert <gruel@web.de>
8     *               2008      Jason Garrett-Glaser <darkshikari@gmail.com>
9   *   *
10   *  This program is free software ; you can redistribute it and/or modify   *  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   *  it under the terms of the GNU General Public License as published by
# Line 25  Line 26 
26   ****************************************************************************/   ****************************************************************************/
27    
28  #include <stdlib.h>  #include <stdlib.h>
29    #include <stdio.h>
30    #include <math.h>
31    
32  #include "../xvid.h"  #include "../xvid.h"
33    #include "../global.h"
34  #include "../portab.h"  #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            int method;
46    } lumi_data_t;
47    
48  /*****************************************************************************  /*****************************************************************************
49   * Prototypes   * Sub plugin functions
50   ****************************************************************************/   ****************************************************************************/
51    
52  static int  static int lumi_plg_info(xvid_plg_info_t *info);
53  adaptive_quantization(unsigned char *buf,  static int lumi_plg_create(xvid_plg_create_t *create, lumi_data_t **handle);
54                                            int stride,  static int lumi_plg_destroy(lumi_data_t *handle, xvid_plg_destroy_t * destroy);
55                                            int *intquant,  static int lumi_plg_frame(lumi_data_t *handle, xvid_plg_data_t *data);
56                                            int framequant,  static int lumi_plg_after(lumi_data_t *handle, xvid_plg_data_t *data);
                                           int min_quant,  
                                           int max_quant,  
                                           int mb_width,  
                                           int mb_height);  
   
57    
58  /*****************************************************************************  /*****************************************************************************
59   * The plugin entry   * The plugin entry function
60   ****************************************************************************/   ****************************************************************************/
61    
62  int  int
63  xvid_plugin_lumimasking(void * handle, int opt, void * param1, void * param2)  xvid_plugin_lumimasking(void * handle, int opt, void * param1, void * param2)
64  {  {
65          switch(opt)          switch(opt) {
         {  
66          case XVID_PLG_INFO :          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                  xvid_plg_info_t * info = (xvid_plg_info_t*)param1;          /* We just require a diff quant array access */
91                  info->flags = XVID_REQDQUANTS;                  info->flags = XVID_REQDQUANTS;
92                  return 0;          return(0);
93          }          }
94    
95          case XVID_PLG_CREATE :  /*----------------------------------------------------------------------------
96          case XVID_PLG_DESTROY :   * Create plugin function
97                  return 0;   *
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            xvid_plugin_lumimasking_t *param = (xvid_plugin_lumimasking_t *) create->param;
106    
107          case XVID_PLG_BEFORE :          if ((lumi = (lumi_data_t*)malloc(sizeof(lumi_data_t))) == NULL)
108                    return(XVID_ERR_MEMORY);
109    
110            lumi->method = 0;
111            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            if (param != NULL)
125                    lumi->method = param->method;
126    
127            /* 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                  xvid_plg_data_t * data = (xvid_plg_data_t*)param1;          if (handle) {
143                  data->quant =                  if (handle->quant) {
144                          adaptive_quantization(data->current.plane[0],                          free(handle->quant);
145                                                                    data->current.stride[0],                          handle->quant = NULL;
146                                                                    data->dquant,                  }
147                                                                    data->quant /* framequant*/,                  if (handle->val) {
148                                                                    data->quant /* min_quant */,                          free(handle->val);
149                                                                    data->quant*2 /* max_quant */,                          handle->val = NULL;
150                                                                    data->mb_width,                  }
151                                                                    data->mb_height);                  free(handle);
152            }
153            return(0);
154    }
155    
156                  return 0;  /*----------------------------------------------------------------------------
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            /* 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            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                            int k, l, sum = 0, sum_of_squares = 0;
195                            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                            if (handle->method) { /* Variance masking mode */
207                                    int variance = 0;
208                                    /* 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                                    variance = sum_of_squares - sum * sum / 256;
218                                    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    
226          case XVID_PLG_AFTER :                                  handle->val[j*data->mb_width + i] = (float)sum/256.0f;
227                  return 0;  
228                                    /* Accumulate the global frame luminance */
229                                    global += (float)sum/256.0f;
230                            }
231                    }
232            }
233    
234            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    
250                    DarkThres = DarkThres*global/127.0f;
251                    BrightThres = BrightThres*global/127.0f;
252    
253    
254                    /* 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    
258                            /* 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                            }
267                    }
268            }
269    
270            /* Normalize the quantizer field */
271            data->quant = normalize_quantizer_field(handle->quant,
272                                                                                             data->dquant,
273                                                                                             data->mb_width*data->mb_height,
274                                                                                             data->quant,
275                                                                                             MAX(2,data->quant + data->quant/2));
276    
277            /* Plugin job finished */
278            return(0);
279          }          }
280    
281          return XVID_ERR_FAIL;  /*----------------------------------------------------------------------------
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  /*****************************************************************************  /*****************************************************************************
# Line 142  Line 340 
340    
341          return (int) (in[0] + 0.5);          return (int) (in[0] + 0.5);
342  }  }
   
 static int  
 adaptive_quantization(unsigned char *buf,  
                                           int stride,  
                                           int *intquant,  
                                           int framequant,  
                                           int min_quant,  
                                           int max_quant,  
                                           int mb_width,  
                                           int mb_height)        /* no qstride because normalization */  
 {  
         int i, j, k, l;  
   
         float *quant;  
         unsigned char *ptr;  
         float *val;  
         float global = 0.;  
         uint32_t mid_range = 0;  
   
         const float DarkAmpl = 14 / 2;  
         const float BrightAmpl = 10 / 2;  
         const float DarkThres = 70;  
         const float BrightThres = 200;  
   
         const float GlobalDarkThres = 60;  
         const float GlobalBrightThres = 170;  
   
         const float MidRangeThres = 20;  
         const float UpperLimit = 200;  
         const float LowerLimit = 25;  
   
   
         if (!(quant = (float *) malloc(mb_width * mb_height * sizeof(float))))  
                 return(-1);  
   
         if(!(val = (float *) malloc(mb_width * mb_height * sizeof(float))))  
                 return(-1);  
   
         for (k = 0; k < mb_height; k++) {  
                 for (l = 0; l < mb_width; l++)  /* do this for all macroblocks individually  */  
                 {  
                         quant[k * mb_width + l] = (float) framequant;  
   
                         /* calculate luminance-masking */  
                         ptr = &buf[16 * k * stride + 16 * l];   /* address of MB */  
   
                         val[k * mb_width + l] = 0.;  
   
                         for (i = 0; i < 16; i++)  
                                 for (j = 0; j < 16; j++)  
                                         val[k * mb_width + l] += ptr[i * stride + j];  
                         val[k * mb_width + l] /= 256.;  
                         global +=val[k * mb_width + l];  
   
                         if ((val[k * mb_width + l] > LowerLimit) &&  
                                 (val[k * mb_width + l] < UpperLimit))  
                                 mid_range++;  
                 }  
         }  
   
         global /=mb_width * mb_height;  
   
         if (((global <GlobalBrightThres) &&(global >GlobalDarkThres))  
                 || (mid_range < MidRangeThres)) {  
                 for (k = 0; k < mb_height; k++) {  
                         for (l = 0; l < mb_width; l++)  /* do this for all macroblocks individually */  
                         {  
                                 if (val[k * mb_width + l] < DarkThres)  
                                         quant[k * mb_width + l] +=  
                                                 DarkAmpl * (DarkThres -  
                                                                         val[k * mb_width + l]) / DarkThres;  
                                 else if (val[k * mb_width + l] > BrightThres)  
                                         quant[k * mb_width + l] +=  
                                                 BrightAmpl * (val[k * mb_width + l] -  
                                                                           BrightThres) / (255 - BrightThres);  
                         }  
                 }  
         }  
   
         i = normalize_quantizer_field(quant, intquant,  
                                                                   mb_width * mb_height,  
                                                                   min_quant, max_quant);  
   
         free(val);  
         free(quant);  
   
         return(i);  
   
 }  

Legend:
Removed from v.1.1.2.4  
changed lines
  Added in v.1.8

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