Example #1
0
static int
lumi_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.0;
	BrightThres = BrightThres*global/127.0;


	/* 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);
}
static int
lumi_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;

    /* Arbitrary centerpoint for variance-based AQ.  Roughly the same as used in x264. */
    float center = 14000.f;
    /* Arbitrary strength for variance-based AQ. */
    float strength = 0.2f;

    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, sum_of_squares = 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;

            if (handle->method) { /* Variance masking mode */
                int variance = 0;
                /* Accumulate sum and sum of squares over the MB */
                for (k = 0; k < 16; k++) {
                    for (l = 0; l < 16; l++) {
                        int val = ptr[k*data->current.stride[0] + l];
                        sum += val;
                        sum_of_squares += val * val;
                    }
                }
                /* Variance = SSD - SAD^2 / (numpixels) */
                variance = sum_of_squares - sum * sum / 256;
                handle->val[j*data->mb_width + i] = (float)variance;
            }
            else { /* Luminance masking mode */
                /* 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;
            }
        }
    }

    if (handle->method) { /* Variance masking */
        /* Apply the variance masking formula to all MBs */
        for (i = 0; i < data->mb_height; i++)
        {
            for (j = 0; j < data->mb_width; j++)
            {
                float value = handle->val[i*data->mb_width + j];
                float qscale_diff = strength * logf(value / center);
                handle->quant[i*data->mb_width + j] *= (1.0f + qscale_diff);
            }
        }
    }
    else { /* Luminance masking */
        /* 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,
                                            MAX(2,data->quant + data->quant/2));

    /* Plugin job finished */
    return(0);
}