about summary refs log tree commit diff
path: root/converter/ppm/ppmtompeg/opts.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtompeg/opts.c')
-rw-r--r--converter/ppm/ppmtompeg/opts.c536
1 files changed, 536 insertions, 0 deletions
diff --git a/converter/ppm/ppmtompeg/opts.c b/converter/ppm/ppmtompeg/opts.c
new file mode 100644
index 00000000..c4d0c0b3
--- /dev/null
+++ b/converter/ppm/ppmtompeg/opts.c
@@ -0,0 +1,536 @@
+/*===========================================================================*
+ * opts.c								     *
+ *									     *
+ *      Special C code to handle TUNEing options                             *
+ *									     *
+ * EXPORTED PROCEDURES:							     *
+ *      Tune_Init                                                            *
+ *      CollectQuantStats                                                    *
+ *									     *
+ *===========================================================================*/
+
+
+/*
+ * Copyright (c) 1995 The Regents of the University of California.
+ * All rights reserved.
+ * 
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+/*==============*
+ * HEADER FILES *
+ *==============*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include "opts.h"
+
+/*==============*
+ * EXTERNALS    *
+ *==============*/
+
+extern char    outputFileName[];
+extern boolean pureDCT;
+extern int32   qtable[], niqtable[];
+extern int     ZAG[];
+extern boolean printSNR, decodeRefFrames;
+
+void init_idctref _ANSI_ARGS_((void));
+void init_fdct _ANSI_ARGS_((void));
+
+
+/*===================*
+ * GLOBALS MADE HERE *
+ *===================*/
+
+boolean tuneingOn = FALSE;
+int block_bound = 128;
+boolean collect_quant = FALSE;
+int collect_quant_detailed = 0;
+FILE *collect_quant_fp;
+int kill_dim = FALSE;
+int kill_dim_break, kill_dim_end;
+float kill_dim_slope;
+int SearchCompareMode = DEFAULT_SEARCH;
+boolean squash_small_differences = FALSE;
+int SquashMaxLum, SquashMaxChr;
+float LocalDCTRateScale = 1.0, LocalDCTDistortScale = 1.0;
+boolean IntraPBAllowed = TRUE;
+boolean WriteDistortionNumbers = FALSE;
+int collect_distortion_detailed = 0;
+FILE *distortion_fp;
+FILE *fp_table_rate[31], *fp_table_dist[31];
+boolean DoLaplace = FALSE;
+double **L1, **L2, **Lambdas;
+int LaplaceNum, LaplaceCnum;
+boolean BSkipBlocks = TRUE;
+
+/* define this as it too much of a pain to find toupper on different arch'es */
+#define ASCII_TOUPPER(c) ((c>='a') && (c<='z')) ? c-'a'+'A' : c
+
+/*===============*
+ * Internals     *
+ *===============*/
+
+/*===========================================================================*
+ *
+ * SkipSpacesTabs
+ *
+ *	skip all spaces and tabs
+ *
+ * RETURNS:	point to next character not a space or tab
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static const char *
+SkipSpacesTabs(const char * const start) {
+
+    const char * p;
+
+    for (p = start; *p == ' ' || *p == '\t'; ++p);
+
+    return p;
+}
+
+
+
+/*===========================================================================*
+ *
+ * SetupCollectQuantStats
+ *
+ *     Setup variables to collect statistics on quantization values
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    sets collect_quant and collect_quant_fp
+ *
+ *===========================================================================*/
+static void 
+SetupCollectQuantStats(const char * const charPtr)
+{
+  char fname[256];
+  const char * cp;
+  cp = charPtr;
+  while ( (*cp != ' ') && (*cp != '\t') && (*cp != '\n')) {
+    cp++;
+  }
+
+  strncpy(fname, charPtr, cp-charPtr);
+  fname[cp-charPtr] = '\0';
+  collect_quant = TRUE;
+  if ((collect_quant_fp = fopen(fname,"w")) == NULL) {
+    fprintf(stderr, "Error opening %s for quant statistics\n", fname);
+    fprintf(stderr, "Using stdout (ick!)\n");
+    collect_quant_fp = stdout;
+  }
+
+  cp = SkipSpacesTabs(cp);
+  if (*cp != '\n') {
+    switch (*cp) {
+    case 'c':
+      collect_quant_detailed = 1;
+      break;
+    default:
+      fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp);
+    }}
+}
+
+
+
+
+/*===========================================================================*
+ *
+ * SetupKillDimAreas
+ *
+ *     Do a transform on small lum values
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    sets kill_dim, kill_dim_break, kill_dim_end
+ *
+ *===========================================================================*/
+static void 
+SetupKillDimAreas(const char * const charPtr)
+{
+  int items_scanned;
+
+  kill_dim = TRUE;
+  items_scanned = sscanf(charPtr, "%d %d %f", 
+			 &kill_dim_break, &kill_dim_end, &kill_dim_slope);
+  if (items_scanned != 3) {
+    kill_dim_slope = 0.25;
+    items_scanned = sscanf(charPtr, "%d %d", 
+			   &kill_dim_break, &kill_dim_end);
+    if (items_scanned != 2) {
+      /* Use defaults */
+      kill_dim_break = 20;
+      kill_dim_end   = 25;
+    }
+  }
+  /* check values */
+  if (kill_dim_break > kill_dim_end) {
+    fprintf(stderr, "TUNE parameter k: break > end is illegal.\n");
+    exit(-1);
+  }
+  if (kill_dim_slope < 0) {
+    fprintf(stderr, "TUNE parameter k: slope < 0 is illegal.\n");
+    exit(-1);
+  }
+}
+
+
+
+/*===========================================================================*
+ *
+ * SetupSquashSmall
+ *
+ *     Setup encoder to squash small changes in Y or Cr/Cb values
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    sets squash_max_differences SquashMaxLum SquashMaxChr 
+ *
+ *===========================================================================*/
+static void 
+SetupSquashSmall(const char * const charPtr)
+{
+  squash_small_differences = TRUE;
+
+  if (sscanf(charPtr, "%d %d", &SquashMaxLum, &SquashMaxChr) == 1) {
+    /* Only set one, do both */
+    SquashMaxChr = SquashMaxLum;
+  }
+}
+
+
+/*===========================================================================*
+ *
+ * SetupLocalDCT
+ *
+ *     Setup encoder to use DCT for rate-distortion estimat ein Psearches
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    sets SearchCompareMode and
+ *                        can change LocalDCTRateScale, LocalDCTDistortScale
+ *
+ *===========================================================================*/
+static void 
+SetupLocalDCT(const char * const charPtr)
+{
+  int num_scales=0;
+
+  SearchCompareMode = LOCAL_DCT;
+
+  /* Set scaling factors if present */
+  num_scales = sscanf(charPtr, "%f %f", &LocalDCTRateScale, &LocalDCTDistortScale);
+  if (num_scales == 1) {
+    fprintf(stderr, "Invalid number of scaling factors for local DCT\n");
+    fprintf(stderr, "Must specify Rate Scale and Distorion scale (both floats)\n");
+    fprintf(stderr, "Continuing with 1.0 1.0\n");
+    LocalDCTRateScale = 1.0;
+    LocalDCTDistortScale = 1.0;
+  }
+}
+
+
+/*===========================================================================*
+ *
+ * SetupLaplace
+ *
+ *     Setup encoder to find distrubution for I-frames, and use for -snr
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    sets DoLaplace, L1, L2, and Lambdas
+ *
+ *===========================================================================*/
+static void 
+SetupLaplace()
+{
+  int i;
+
+  DoLaplace = TRUE;
+  LaplaceNum = 0;
+  L1 = (double **)malloc(sizeof(double *)*3);
+  L2 = (double **)malloc(sizeof(double *)*3);
+  Lambdas = (double **)malloc(sizeof(double *)*3);
+  if (L1 == NULL || L2 == NULL || Lambdas == NULL) {
+    fprintf(stderr,"Out of memory!!!\n");
+    exit(1);
+  }
+  for (i = 0; i < 3; i++) {
+    L1[i] = (double *)calloc(64, sizeof(double));
+    L2[i] = (double *)calloc(64, sizeof(double));
+    Lambdas[i] = (double *)malloc(sizeof(double) * 64);
+    if (L1[i] == NULL || L2[i] == NULL || Lambdas[i] == NULL) {
+      fprintf(stderr,"Out of memory!!!\n");
+      exit(1);
+    }
+  }
+}
+
+static void
+SetupWriteDistortions(const char * const charPtr)
+{
+  char fname[256];
+  const char * cp;
+  int i;
+
+  WriteDistortionNumbers = TRUE;
+  cp = charPtr;
+  while ( (*cp != ' ') && (*cp != '\t') && (*cp != '\n')) {
+    cp++;
+  }
+
+  strncpy(fname, charPtr, cp-charPtr);
+  fname[cp-charPtr] = '\0';
+  collect_quant = TRUE;
+  if ((distortion_fp = fopen(fname,"w")) == NULL) {
+    fprintf(stderr, "Error opening %s for quant statistics\n", fname);
+    fprintf(stderr, "Using stdout (ick!)\n");
+    distortion_fp = stdout;
+  }
+
+  cp = SkipSpacesTabs(cp);
+  if (*cp != '\n') {
+    switch (*cp) {
+    case 'c':
+      collect_distortion_detailed = TRUE;
+      break;
+    case 't': {
+      char scratch[256];
+      collect_distortion_detailed = 2;
+      for (i = 1;  i < 32;  i++) {
+	sprintf(scratch, "%srate%d", fname, i);
+	fp_table_rate[i-1] = fopen(scratch, "w");
+	sprintf(scratch, "%sdist%d", fname, i);
+	fp_table_dist[i-1] = fopen(scratch, "w");
+	}}
+      break;
+    default:
+      fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp);
+    }}
+}  
+
+/*=====================*
+ * EXPORTED PROCEDURES *
+ *=====================*/
+
+void 
+CalcLambdas(void) {
+
+  int i,j,n;
+  double var;
+  
+  n = LaplaceNum;
+  for (i = 0;   i < 3;  i++) {
+    for (j = 0;  j < 64;  j++) {
+      var = (n*L1[i][j] + L2[i][j]*L2[i][j]) / (n*(n-1));
+      Lambdas[i][j] = sqrt(2.0) / sqrt(var);
+    }
+  }
+}
+
+
+/*===========================================================================*
+ *
+ * Mpost_UnQuantZigBlockLaplace
+ *
+ *	unquantize and zig-zag (decode) a single block, using the distrib to get vals
+ *      Iblocks only now
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+void
+Mpost_UnQuantZigBlockLaplace(in, out, qscale, iblock)
+    FlatBlock in;
+    Block out;
+    int qscale;
+    boolean iblock;
+{
+    register int index;
+    int	    position;
+    register int	    qentry;
+    int	    level, coeff;
+    double low, high;
+    double mid,lam;
+
+    /* qtable[0] must be 8 */
+    out[0][0] = (int16)(in[0] * 8);
+    
+    for ( index = 1;  index < DCTSIZE_SQ;  index++ ) {
+      position = ZAG[index];
+      level = in[index];
+      
+      if (level == 0) {
+	((int16 *)out)[position] = 0;
+	continue;
+      }
+      qentry = qtable[position] * qscale;
+      coeff = (level*qentry)/8;
+      low = ((ABS(level)-.5)*qentry)/8;
+      high = ((ABS(level)+.5)*qentry)/8;
+      lam = Lambdas[LaplaceCnum][position];
+      mid = (1.0/lam) * log(0.5*(exp(-lam*low)+exp(-lam*high)));
+      mid = ABS(mid);
+      if (mid - floor(mid) > .4999) {
+	mid = ceil(mid);
+      } else {
+	mid = floor(mid);
+      }
+      if (level<0) {mid = -mid;}
+/*printf("(%2.1lf-%2.1lf): old: %d vs %d\n",low,high,coeff,(int) mid);*/
+      coeff = mid;
+      if ( (coeff & 1) == 0 ) {
+	if ( coeff < 0 ) {
+	  coeff++;
+	} else if ( coeff > 0 ) {
+	  coeff--;
+	}
+      }
+      ((int16 *)out)[position] = coeff;
+    }
+}
+
+int 
+mse(Block blk1, Block blk2)
+{
+  register int index, error, tmp;
+  int16 *bp1, *bp2;
+
+  bp1 = (int16 *)blk1;
+  bp2 = (int16 *)blk2;
+  error = 0;
+  for ( index = 0;  index < DCTSIZE_SQ;  index++ ) {
+    tmp = *bp1++ - *bp2++;
+    error += tmp*tmp;
+  }
+  return error;
+}
+
+
+
+
+/*===========================================================================*
+ *
+ * Tune_Init
+ *
+ *     Do any setup needed before coding stream
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:  varies
+ *
+ *===========================================================================*/
+void Tune_Init()
+{
+  int i;
+
+  /* Just check for each, and do whats needed */
+  if (collect_quant) {
+    if (!pureDCT) {
+      pureDCT = TRUE;
+      init_idctref();
+      init_fdct();
+    }
+    fprintf(collect_quant_fp, "# %s\n", outputFileName);
+    fprintf(collect_quant_fp, "#");
+    for (i=0; i<64; i++) 
+      fprintf(collect_quant_fp, " %d", qtable[i]);
+    fprintf(collect_quant_fp, "\n#");
+    for (i=0; i<64; i++) 
+      fprintf(collect_quant_fp, " %d", niqtable[i]);
+    fprintf(collect_quant_fp, "\n# %d %d %d\n\n", 
+	    GetIQScale(), GetPQScale(), GetBQScale());
+    
+  }
+
+  if (DoLaplace) {
+    if (!pureDCT) {
+      pureDCT = TRUE;
+      init_idctref();
+      init_fdct();
+    }
+    decodeRefFrames = TRUE;
+    printSNR = TRUE;
+  }
+    
+}
+
+/*===========================================================================*
+ *
+ * ParseTuneParam
+ *
+ *     Handle the strings following TUNE
+ *
+ * RETURNS:	nothing
+ *
+ * SIDE EFFECTS:  varies
+ *
+ *===========================================================================*/
+void ParseTuneParam(const char * const charPtr)
+{
+  switch (ASCII_TOUPPER(*charPtr)) {
+  case 'B': 
+    if (1 != sscanf(charPtr+2, "%d", &block_bound)) {
+      fprintf(stderr, "Invalid tuning parameter (b) in parameter file.\n");
+    }
+    break;
+  case 'C':
+    SetupCollectQuantStats(charPtr+2);
+    break;
+  case 'D':
+    SetupLocalDCT(SkipSpacesTabs(charPtr+1));
+    break;
+  case 'K':
+    SetupKillDimAreas(SkipSpacesTabs(charPtr+1));
+    break;
+  case 'L':
+    SetupLaplace();
+    break;
+  case 'N':
+    SearchCompareMode = NO_DC_SEARCH;
+    break;
+  case 'Q':
+    SearchCompareMode = DO_Mean_Squared_Distortion;
+    break;
+  case 'S':
+    SetupSquashSmall(SkipSpacesTabs(charPtr+1));
+    break;
+  case 'W':
+    SetupWriteDistortions(SkipSpacesTabs(charPtr+1));
+    break;
+  case 'U':
+    BSkipBlocks = FALSE;
+    break;
+  case 'Z':
+     IntraPBAllowed = FALSE;
+    break;
+  default:
+    fprintf(stderr, "Unknown tuning (%s) in parameter file.\n",charPtr);
+    break;
+  }
+}
+
+