📄 plugin_lumimasking.c
字号:
/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - XviD plugin: performs a lumimasking algorithm on encoded frame - * * Copyright(C) 2002-2003 Peter Ross <pross@xvid.org> * 2002 Christoph Lampert <gruel@web.de> * * This program is free software ; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation ; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY ; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program ; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: plugin_lumimasking.c,v 1.3 2004/04/02 22:20:31 suxen_drol Exp $ * ****************************************************************************/#include <stdlib.h>#include "../xvid.h"#include "../portab.h"#include "../utils/emms.h"/***************************************************************************** * Private data type ****************************************************************************/typedef struct{ float *quant; float *val;} lumi_data_t;/***************************************************************************** * Sub plugin functions ****************************************************************************/static int lumi_plg_info(xvid_plg_info_t *info);static int lumi_plg_create(xvid_plg_create_t *create, lumi_data_t **handle);static int lumi_plg_destroy(lumi_data_t *handle, xvid_plg_destroy_t * destroy);static int lumi_plg_frame(lumi_data_t *handle, xvid_plg_data_t *data);static int lumi_plg_after(lumi_data_t *handle, xvid_plg_data_t *data);/***************************************************************************** * The plugin entry function ****************************************************************************/intxvid_plugin_lumimasking(void * handle, int opt, void * param1, void * param2){ switch(opt) { case XVID_PLG_INFO: return(lumi_plg_info((xvid_plg_info_t*)param1)); case XVID_PLG_CREATE: return(lumi_plg_create((xvid_plg_create_t *)param1, (lumi_data_t **)param2)); case XVID_PLG_DESTROY: return(lumi_plg_destroy((lumi_data_t *)handle, (xvid_plg_destroy_t*)param1)); case XVID_PLG_BEFORE : return 0; case XVID_PLG_FRAME : return(lumi_plg_frame((lumi_data_t *)handle, (xvid_plg_data_t *)param1)); case XVID_PLG_AFTER : return(lumi_plg_after((lumi_data_t *)handle, (xvid_plg_data_t *)param1)); } return(XVID_ERR_FAIL);}/*---------------------------------------------------------------------------- * Info plugin function *--------------------------------------------------------------------------*/static intlumi_plg_info(xvid_plg_info_t *info){ /* We just require a diff quant array access */ info->flags = XVID_REQDQUANTS; return(0);}/*---------------------------------------------------------------------------- * Create plugin function * * Allocates the private plugin data arrays *--------------------------------------------------------------------------*/static intlumi_plg_create(xvid_plg_create_t *create, lumi_data_t **handle){ lumi_data_t *lumi; if ((lumi = (lumi_data_t*)malloc(sizeof(lumi_data_t))) == NULL) return(XVID_ERR_MEMORY); lumi->quant = (float*)malloc(create->mb_width*create->mb_height*sizeof(float)); if (lumi->quant == NULL) { free(lumi); return(XVID_ERR_MEMORY); } lumi->val = (float*)malloc(create->mb_width*create->mb_height*sizeof(float)); if (lumi->val == NULL) { free(lumi->quant); free(lumi); return(XVID_ERR_MEMORY); } /* Bind the data structure to the handle */ *handle = lumi; return(0);}/*---------------------------------------------------------------------------- * Destroy plugin function * * Free the private plugin data arrays *--------------------------------------------------------------------------*/static intlumi_plg_destroy(lumi_data_t *handle, xvid_plg_destroy_t *destroy){ if (handle) { if (handle->quant) { free(handle->quant); handle->quant = NULL; } if (handle->val) { free(handle->val); handle->val = NULL; } free(handle); } return(0);}/*---------------------------------------------------------------------------- * Before plugin function * * Here is all the magic about lumimasking. *--------------------------------------------------------------------------*//* Helper function defined later */static int normalize_quantizer_field(float *in, int *out, int num, int min_quant, int max_quant);static intlumi_plg_frame(lumi_data_t *handle, xvid_plg_data_t *data){ int i, j; float global = 0.0f; const float DarkAmpl = 14 / 4; const float BrightAmpl = 10 / 3; float DarkThres = 90; float BrightThres = 200; const float GlobalDarkThres = 60; const float GlobalBrightThres = 170; if (data->type == XVID_TYPE_BVOP) return 0; /* Do this for all macroblocks individually */ for (j = 0; j < data->mb_height; j++) { for (i = 0; i < data->mb_width; i++) { int k, l, sum = 0; unsigned char *ptr; /* Initialize the current quant value to the frame quant */ handle->quant[j*data->mb_width + i] = (float)data->quant; /* Next steps compute the luminance-masking */ /* Get the MB address */ ptr = data->current.plane[0]; ptr += 16*j*data->current.stride[0] + 16*i; /* Accumulate luminance */ for (k = 0; k < 16; k++) for (l = 0; l < 16; l++) sum += ptr[k*data->current.stride[0] + l]; handle->val[j*data->mb_width + i] = (float)sum/256.0f; /* Accumulate the global frame luminance */ global += (float)sum/256.0f; } } /* Normalize the global luminance accumulator */ global /= data->mb_width*data->mb_height; DarkThres = DarkThres*global/127.0f; BrightThres = BrightThres*global/127.0f; /* Apply luminance masking only to frames where the global luminance is * higher than DarkThreshold and lower than Bright Threshold */ if ((global < GlobalBrightThres) && (global > GlobalDarkThres)) { /* Apply the luminance masking formulas to all MBs */ for (i = 0; i < data->mb_height; i++) { for (j = 0; j < data->mb_width; j++) { if (handle->val[i*data->mb_width + j] < DarkThres) handle->quant[i*data->mb_width + j] *= 1 + DarkAmpl * (DarkThres - handle->val[i*data->mb_width + j]) / DarkThres; else if (handle->val[i*data->mb_width + j] > BrightThres) handle->quant[i*data->mb_width + j] *= 1 + BrightAmpl * (handle->val[i*data->mb_width + j] - BrightThres) / (255 - BrightThres); } } } /* Normalize the quantizer field */ data->quant = normalize_quantizer_field(handle->quant, data->dquant, data->mb_width*data->mb_height, data->quant, data->quant + data->quant/2); /* Plugin job finished */ return(0);}/*---------------------------------------------------------------------------- * After plugin function (dummy function) *--------------------------------------------------------------------------*/static intlumi_plg_after(lumi_data_t *handle, xvid_plg_data_t *data){ return(0);}/***************************************************************************** * Helper functions ****************************************************************************/#define RDIFF(a, b) ((int)(a+0.5)-(int)(b+0.5))static intnormalize_quantizer_field(float *in, int *out, int num, int min_quant, int max_quant){ int i; int finished; do { finished = 1; for (i = 1; i < num; i++) { if (RDIFF(in[i], in[i - 1]) > 2) { in[i] -= (float) 0.5; finished = 0; } else if (RDIFF(in[i], in[i - 1]) < -2) { in[i - 1] -= (float) 0.5; finished = 0; } if (in[i] > max_quant) { in[i] = (float) max_quant; finished = 0; } if (in[i] < min_quant) { in[i] = (float) min_quant; finished = 0; } if (in[i - 1] > max_quant) { in[i - 1] = (float) max_quant; finished = 0; } if (in[i - 1] < min_quant) { in[i - 1] = (float) min_quant; finished = 0; } } } while (!finished); out[0] = 0; for (i = 1; i < num; i++) out[i] = RDIFF(in[i], in[i - 1]); return (int) (in[0] + 0.5);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -