📄 bw.c
字号:
#define SCENE
#define noDITHER 1
#define noDUMPSTAT 1
/*------------------------------------------------------------------------
$Workfile: BW.C $
$Date: 2/03/97 10:23a $
$Revision: 18 $
* Purpose:
*
* Notes:
*
$History: BW.C $
*
* ***************** Version 18 *****************
* User: Az Date: 2/03/97 Time: 10:23a
* Updated in $/601cman
*
* ***************** Version 17 *****************
* User: Az Date: 1/17/97 Time: 9:35a
* Updated in $/601cman
* Fixed up default values for feedback.
* Disabled dithering and scene detection .
*
* ***************** Version 16 *****************
* User: Stevel Date: 12/16/96 Time: 6:41p
* Updated in $/icm
* Fix a compiling error.
*
* ***************** Version 15 *****************
* User: Az Date: 12/16/96 Time: 4:39p
* Updated in $/icm
* Made no-feedback default (important for ICM)
* Also, cancel the feedback in case special effects are required.
*
* ***************** Version 14 *****************
* User: Az Date: 12/16/96 Time: 10:53a
* Updated in $/icm
*
* ***************** Version 11 *****************
* User: Az Date: 12/12/96 Time: 5:51p
* Updated in $/601cman
* Deleted a kludge.
*
* ***************** Version 10 *****************
* User: Az Date: 12/12/96 Time: 5:47p
* Updated in $/601cman
* Changed scene detection demo feature to preserve, more or less,
* the bit rate.
* Change in the feedback control: when the bit rate goes down,
* the feedback gain used is only one half of the case when the bit
* rate is too high.
* On scene change, switch to "conservative mode", i.e.
* feedback adjustment is set to 1.5 instead of 1.0.
*
* ***************** Version 9 *****************
* User: Az Date: 12/12/96 Time: 1:21p
* Updated in $/601cman
* Disabled feedback during "screwed up" fields in scene detection.
*
* ***************** Version 8 *****************
* User: Az Date: 12/11/96 Time: 5:32p
* Updated in $/601cman
* Mixed in Hakan's noise reduction code.
*
* ***************** Version 7 *****************
* User: Az Date: 12/10/96 Time: 1:33p
* Updated in $/601cman
* Lots of changed lines. Functionally, Scene Detection and
* Feedback Control added.
*
* ***************** Version 5 *****************
* User: Az Date: 10/18/96 Time: 12:33a
* Updated in $/601cman
* Added function "read_config_file". Modified config parameters
* slightly.
*
* ***************** Version 4 *****************
* User: Stevel Date: 10/08/96 Time: 11:19a
* Updated in $/601cman
* Fixed a typo.
*
* ***************** Version 3 *****************
* User: Az Date: 10/08/96 Time: 4:52a
* Updated in $/601cman
* Modified the clipping of the bin widths.
* Also, modified the configuration table slightly.
*
* ***************** Version 2 *****************
* User: Az Date: 10/04/96 Time: 4:34a
* Updated in $/icm
* Added clipping of bin widths (currently to 70).
*
* ***************** Version 1 *****************
* User: Stevel Date: 10/03/96 Time: 2:10p
* Created in $/601cman
* New Bin Width Calculator.
This code and information is provided "as is" without warranty of any
kind, either expressed or implied, including but not limited to the
implied warranties of merchantability and/or fitness for a particular
purpose.
1996 Analog Devices, Inc.
-------------------------------------------------------------------------*/
/******************************************************************
BIN WIDTH CALCULATOR
Copyright Analog Devices 1995,1996
by Alex Zatsman.
This is the bin width calculator for ADV601. The general
principal is relatively simple: we have a family of bin width
sets. When given the statistis and the target bit rate, we try to
evaluate which family gets the closest match. The sets are
parameterized by a single variable ("tau" in this code), and we
use binary search (in bw_compute) to find the best match.
We assume that we can estimate what the actual bit rate will be
depending on the statistics and the bin width (see function
"estimate_bpp"). To make the predictions, the tables from file
bw3tab.c are used. Each 2D table is indexed by block number and
"normalized logarithmic bin width index" (NLBWI). The latter is
simply logarithm of ratio of BW to the standard deviation of the
signal in the block, i.e. square root of the statistics. The
estimation is done in the function "estimate_bpp" by linear
interpolation of the table.
Note that there are three tables: one for natural images, one for
so-called "synthetic" (like cartoons and drawings) and one
"general", i.e. when we don't know in advance what type of image
we are going to use.
The feature described in the following paragraph is obsolete as
of Sept. 1996 because ADV601 is no longer vulnerable to bursts
(as of Rev.0.4).
For systems which are sensitive to data bursts in low-pass blocks
there are two ways to cope: using "burst fuse" function or
defining "LOWFIX" constant. The former is more adaptive: it
checks the statistics and makes sure that the bin widths force
the quantized value within certain limits (those limits can be
configured by adjusting config_rec.MaxQValwInv). This is a nicer
scheme, but if BWC takes to long, it will not get the "safe"
values of bin widths in time for the current frame. The second
fix ("LOWFIX") is less subtle: it simply limits bin widths for
low-pass blocks from below.
******************************************************************/
#include <stdio.h>
#include <math.h>
#ifdef SOFTCODEC
// Define for ICM (adv601.dll)
#include "common.h"
#include "block.h"
#define DLLEXPORT
#define NBLOCKS 42
#else
// Define for 601cman.dll
#define NBLOCKS 42
#include <memory.h>
#include "bit-prec.h"
#endif
char *npsfname = "noise.cfg";
int noise_check_p = 0;
#include "bw.h"
#include "bw3tab.c"
#ifndef FLOAT2HBW
#define FLOAT2HBW(X) FLOAT2FIX(X,8)
#define FLOAT2HBWI(X) FLOAT2FIX(X,10)
#endif
#ifdef sgi
#define LOG10(X) log10f(X)
#else
#define LOG10(X) (float)log10((double)X)
#endif
#define MAXLINE 300
///////////////////////////////////////////////////////////////////////////
// Signal flag used by Bin Width Calculator
///////////////////////////////////////////////////////////////////////////
extern int *pBWrdyFlg;
/*** If LOWFIX is defined, the values of bin widths for blocks
39 (low-pass luminance), 40 and 41 (low-pass chrominance) will be
overwritten by LOWFIX in 39 and LOWFIX/2 in 40 and 41.
This is a crude way of preventing bad bursts of data in those blocks. ***/
#define noLOWFIX 1.1f
/******************************************** CONFIGURATION PARAMETERS: ***/
/***** Initial parameters: these parameters can be set by developers to
fine-tune the system. Parameters ending with '0' are for minimal
compression, while parameters ending with '1' are for maximum
compression. The six arrays below are used to compute
bw_min and bw_max ****/
static real levels0[6] = {0.1f, 0.1f, 0.1f, 0.1f, 0.1f, 0.1f};
static real yuv_bias0[3] = {1.0f, 1.0f, 1.0f};
static real diag_hor_vert0[3] = {1.0f, 1.0f, 1.0f};
static real levels1[6] = {700.0f, 200.0f, 50.0f, 10.0f, 3.0f, 1.0f};
static real yuv_bias1[3] = {1.0f, 1.2f, 1.2f};
static real diag_hor_vert1[3] = {1.3f, 1.0f, 1.0f};
static real clip_levels[6] = {80.0f ,40.0f ,30.0f ,10.0f ,6.0f ,4.0f};
static real clip_yuv_bias[3] = {1.0f, 1.5f, 1.5f};
static real clip_diag_hor_vert[3] = {1.0f, 1.0f, 1.0f};
static real upper_bw_limit = 70.0f;
/* The default values for feedback and scene change are set
so that ICM, which doesn't read the configuration file,
would not use these features */
static float feedback_speed = 0.1f;
static float current_feedback_speed = 0.1f;
static float feedback_scene_thresh = 0.1f;
static float feedback_scene_thresh_2;
static float scene_thresh = 0.1f;
static float scene_thresh_2;
static int need_scene_detection_p = 0;
static int noisebw = 0;
/******** Derived parameters: they are computed using the initial
parameters. ****/
BWCconfig config_rec;
static real bw_min[NBLOCKS]; /* Bin Widths for minimum compression
and best quality */
static real bw_max[NBLOCKS]; /* Bin Widths for maximum compression and
worst quality */
static real bw_noise[NBLOCKS]; /*Minimum Bin Widths for noise */
/* data rate minimization */
static real bw_clip [NBLOCKS];
static int block_sizes [NBLOCKS]; /* Block Sizes in samples */
static real block_weights[NBLOCKS]; /* Share of samples in the block */
static float feedback_adjustment = 1.0f;
//=========================================================================
// Function to configure the Bin Width Calculator
//=========================================================================
DLLEXPORT void bw_config()
{
int bn, lev, dir, color;
config_rec.BppPrecision = 0.05f;
config_rec.BppFeedbackParm[0] = 0.0f;
config_rec.BppFeedbackParm[1] = 0.0f;
config_rec.MaxQVal2Inv = 1.0f / (100.0f*100.0f);
for (bn=0; bn<3; bn++) {
bw_min[bn] = levels0[0] * yuv_bias0[bn];
bw_max[bn] = levels1[0] * yuv_bias1[bn];
bw_clip[bn] = clip_levels[0] * clip_yuv_bias[bn];
}
for (lev=1; lev<6; lev++) {
for (dir=0; dir<3; dir++) {
for (color=0; color<3; color++) {
if (bn < NBLOCKS) {
bw_min[bn] = levels0[lev]
* diag_hor_vert0[dir]
* yuv_bias0[color];
bw_max[bn] = levels1[lev]
* diag_hor_vert1[dir]
* yuv_bias1[color];
bw_clip[bn] = clip_levels[lev]
* clip_diag_hor_vert[dir]
* clip_yuv_bias[color];
bn++;
}
}
}
}
feedback_scene_thresh_2 = feedback_scene_thresh * feedback_scene_thresh;
scene_thresh_2 = scene_thresh * scene_thresh;
}
static void clip_bw (real bwa[])
{
int bn;
for (bn=0; bn<NBLOCKS; bn++) {
if (bwa[bn] >= bw_clip[bn])
bwa[bn] = 0.0f;
}
}
/*** TAU2BW computes the set of BW corresponding to TAU ***/
static void tau2bw(real tau, real bw[])
{
int bn;
for (bn=0; bn<NBLOCKS; bn++)
bw[bn] = (float) pow(bw_min[bn], 1.0f-tau) *
(float ) pow((double)bw_max[bn], (double)tau);
clip_bw(bw);
}
/********************************************************************/
/*** b0 and b1 represent minumum and maximum bin widths for which
the tables used by BWC are computed. */
static real b0 = 0.01f;
static real b1 = 100.0f;
/*** The constants below define scales for statistics values from ADV601.
P24 actually corresponds to 10 bit shift:
there are 14 bits built in into squares of 9.7 values from
the wavelet transform.
P26 corresponds to 12 bit shift, etc. ***/
#define P24 1024.0f
#define P26 (4.0f*P24)
#define P28 (4.0f*P26)
#define P30 (4.0f*P28)
#define P32 (4.0f*P30)
static real v2scale[NBLOCKS] = {
P32, P32, P32,
P30, P30, P30, P30, P30, P30, P30, P30, P30,
P28, P28, P28, P28, P28, P28, P28, P28, P28,
P26, P26, P26, P26, P26, P26, P26, P26, P26,
P24, P24, P24, P24, P24, P24, P24, P24, P24,
P24, P24, P24
};
static real v2scale_log[NBLOCKS];
/*******************************************************/
static real estimate_bpp (real bw[]);
static void tau2bw (real tau, real bw[]);
static void expand_statistics (BWCinput *ip);
static void init_block_sizes (int img_width, int img_height);
/********************************************************Internal Variables **/
real the_rate, rate0, rate1; /* Range of acceptable bit rates. */
static real b1log; /* Logarithm of b1 (see above) */
static real lbw_scale;
static real v2log[NBLOCKS]; /* half log of deviations */
#ifdef BURSTFUSE
static void burst_fuse (BWCinput *bi, real bw[]);
#endif
#ifdef SCENE
/* SCBREAK is the number of fields to be screwed up on scene change */
#define SCBREAK 8
int sc_field_num = 0; /* kind of reverse field number after the break */
static float old_stat[NBLOCKS];
/* two output: one for feedback threshold, another for regular */
static void detect_scene_change (BWCinput *ip, int *fb_sc_p, int *sc_p)
{
int bn;
float dist2=0.0f, olds2=0.0f, vnew, vold, vdiff;
for (bn=0; bn<NBLOCKS; bn++) {
vnew = 0.5f + ((float)(ip->SumOfSq[bn]));
vold = old_stat[bn];
vdiff = vnew - vold;
dist2 += vdiff * vdiff;
olds2 += vold * vold;
old_stat[bn] = vnew;
}
*fb_sc_p = dist2 > feedback_scene_thresh_2 * olds2;
*sc_p = dist2 > scene_thresh_2 * olds2;
}
#endif
#ifdef DUMPSTAT
int stat_fd = -1;
#endif
#ifdef DITHER
#include <stdlib.h>
float dither_range = 0.0f;
float dither_scale = 0.0f;
float dither_base = 1.0f;
#endif
/************************************************ MAIN ENTRY ************/
/* Do binary search on "tau" to get the estimated bit rate
inside [rate0,rate1] interval */
//=========================================================================
// Bin Width Calculation
//=========================================================================
DLLEXPORT void bw_compute (BWCinput *in, BWCoutput *out)
{
real
bw_cur[NBLOCKS],
tau_low = 0.0f,
tau_high = 1.0f,
tau_mid, rhigh, rmid, rlow,
bw, bwr, error_ratio;
int done, bn, sc_change_p, fb_sc_change_p;
unsigned short bw_fixed, bwr_fixed;
#ifdef DUMPSTAT
if (stat_fd > 0)
write (stat_fd, in->SumOfSq, 84);
#endif
expand_statistics(in);
detect_scene_change (in, &fb_sc_change_p, &sc_change_p);
if (sc_change_p) {
if (need_scene_detection_p)
sc_field_num = SCBREAK;
out->scene_change_p = 1;
}
if (fb_sc_change_p)
feedback_adjustment = 1.5f;
else {
if (in->OldBp > 0) {
error_ratio = in->OldBp / the_rate;
if (error_ratio < 1.0f) {
float half_speed = 0.5f * current_feedback_speed;
/**** be more careful about adjusting the BWC upward ****/
feedback_adjustment *=
(half_speed * error_ratio + (1.0f - half_speed));
}
else {
feedback_adjustment *=
(current_feedback_speed * error_ratio +
(1.0f - current_feedback_speed));
/* TEMPORARY FOR DEBUGGING: */
/* feedback_adjustment = 1.0f; */
}
}
}
tau2bw (tau_high, bw_cur);
rlow = estimate_bpp(bw_cur);
if (rlow < rate0) {
tau2bw (tau_low, bw_cur);
rhigh = estimate_bpp(bw_cur);
if (rate1 < rhigh)
{
for (done=0; ! done; ) {
tau_mid = 0.5f*(tau_low + tau_high);
tau2bw (tau_mid, bw_cur);
rmid = estimate_bpp(bw_cur);
if (rmid < rate0) {
rlow = rmid;
tau_high = tau_mid;
}
else if (rmid > rate1) {
rhigh = rmid;
tau_low = tau_mid;
}
else
done = 1;
}
}
}
#ifdef BURSTFUSE
burst_fuse (in, bw_cur);
#endif
#ifdef LOWFIX
if (bw_cur[39] < LOWFIX)
bw_cur[39] = LOWFIX;
if (bw_cur[40] < 0.5 * LOWFIX)
bw_cur[40] = 0.5 * LOWFIX;
if (bw_cur[41] < 0.5 * LOWFIX)
bw_cur[41] = 0.5 * LOWFIX;
#endif
#ifdef DITHER
{
for (bn=0; bn<NBLOCKS; bn++)
bw_cur[bn] *= (dither_base + dither_scale * (float) rand());
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -