ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/freemol/trunk/src/mpeg_encode/src/opts.c
Revision: 74
Committed: Mon Dec 15 04:49:34 2008 UTC (12 years, 9 months ago) by wdelano
File size: 13664 byte(s)
Log Message:
Line File contents
1 /*===========================================================================*
2 * opts.c *
3 * *
4 * Special C code to handle TUNEing options *
5 * *
6 * EXPORTED PROCEDURES: *
7 * Tune_Init *
8 * CollectQuantStats *
9 * *
10 *===========================================================================*/
11
12
13 /*
14 * Copyright (c) 1995 The Regents of the University of California.
15 * All rights reserved.
16 *
17 * Permission to use, copy, modify, and distribute this software and its
18 * documentation for any purpose, without fee, and without written agreement is
19 * hereby granted, provided that the above copyright notice and the following
20 * two paragraphs appear in all copies of this software.
21 *
22 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
23 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
24 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
25 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
28 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
30 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
31 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
32 */
33
34 /*==============*
35 * HEADER FILES *
36 *==============*/
37
38 #include <stdio.h>
39 #include <string.h>
40 #if !defined(__APPLE__)
41 #include <malloc.h>
42 #else
43 #include <stdlib.h>
44 #endif
45 #include <math.h>
46
47 #include "opts.h"
48
49 /*==============*
50 * EXTERNALS *
51 *==============*/
52
53 extern char outputFileName[];
54 extern boolean pureDCT;
55 extern int32 qtable[], niqtable[];
56 extern int ZAG[];
57 extern boolean printSNR, decodeRefFrames;
58
59 void init_idctref _ANSI_ARGS_((void));
60 void init_fdct _ANSI_ARGS_((void));
61
62
63 /*===================*
64 * GLOBALS MADE HERE *
65 *===================*/
66
67 boolean tuneingOn = FALSE;
68 int block_bound = 128;
69 boolean collect_quant = FALSE;
70 int collect_quant_detailed = 0;
71 FILE *collect_quant_fp;
72 int kill_dim = FALSE;
73 int kill_dim_break, kill_dim_end;
74 float kill_dim_slope;
75 int SearchCompareMode = DEFAULT_SEARCH;
76 boolean squash_small_differences = FALSE;
77 int SquashMaxLum, SquashMaxChr;
78 float LocalDCTRateScale = 1.0, LocalDCTDistortScale = 1.0;
79 boolean IntraPBAllowed = TRUE;
80 boolean WriteDistortionNumbers = FALSE;
81 int collect_distortion_detailed = 0;
82 FILE *distortion_fp;
83 FILE *fp_table_rate[31], *fp_table_dist[31];
84 boolean DoLaplace = FALSE;
85 double **L1, **L2, **Lambdas;
86 int LaplaceNum, LaplaceCnum;
87 boolean BSkipBlocks = TRUE;
88
89 /*====================*
90 * Internal Prototypes*
91 *====================*/
92 void SetupCollectQuantStats _ANSI_ARGS_((char *charPtr));
93 void SetupSquashSmall _ANSI_ARGS_ ((char *charPtr));
94 void SetupKillDimAreas _ANSI_ARGS_((char *charPtr));
95 void SetupLocalDCT _ANSI_ARGS_((char *charPtr));
96 void SetupWriteDistortions _ANSI_ARGS_((char *charPtr));
97 void SetupLaplace _ANSI_ARGS_((void));
98 void CalcLambdas _ANSI_ARGS_((void));
99 void Mpost_UnQuantZigBlockLaplace _ANSI_ARGS_((FlatBlock in, Block out, int qscale, boolean iblock));
100
101 /* define this as it too much of a pain to find toupper on different arch'es */
102 #define ASCII_TOUPPER(c) ((c>='a') && (c<='z')) ? c-'a'+'A' : c
103
104 /*=====================*
105 * EXPORTED PROCEDURES *
106 *=====================*/
107
108 /*===========================================================================*
109 *
110 * Tune_Init
111 *
112 * Do any setup needed before coding stream
113 *
114 * RETURNS: nothing
115 *
116 * SIDE EFFECTS: varies
117 *
118 *===========================================================================*/
119 void Tune_Init()
120 {
121 int i;
122
123 /* Just check for each, and do whats needed */
124 if (collect_quant) {
125 if (!pureDCT) {
126 pureDCT = TRUE;
127 init_idctref();
128 init_fdct();
129 }
130 fprintf(collect_quant_fp, "# %s\n", outputFileName);
131 fprintf(collect_quant_fp, "#");
132 for (i=0; i<64; i++)
133 fprintf(collect_quant_fp, " %d", qtable[i]);
134 fprintf(collect_quant_fp, "\n#");
135 for (i=0; i<64; i++)
136 fprintf(collect_quant_fp, " %d", niqtable[i]);
137 fprintf(collect_quant_fp, "\n# %d %d %d\n\n",
138 GetIQScale(), GetPQScale(), GetBQScale());
139
140 }
141
142 if (DoLaplace) {
143 if (!pureDCT) {
144 pureDCT = TRUE;
145 init_idctref();
146 init_fdct();
147 }
148 decodeRefFrames = TRUE;
149 printSNR = TRUE;
150 }
151
152 }
153
154 /*===========================================================================*
155 *
156 * ParseTuneParam
157 *
158 * Handle the strings following TUNE
159 *
160 * RETURNS: nothing
161 *
162 * SIDE EFFECTS: varies
163 *
164 *===========================================================================*/
165 void ParseTuneParam(charPtr)
166 char *charPtr;
167 {
168 switch (ASCII_TOUPPER(*charPtr)) {
169 case 'B':
170 if (1 != sscanf(charPtr+2, "%d", &block_bound)) {
171 fprintf(stderr, "Invalid tuning parameter (b) in parameter file.\n");
172 }
173 break;
174 case 'C':
175 SetupCollectQuantStats(charPtr+2);
176 break;
177 case 'D':
178 SetupLocalDCT(SkipSpacesTabs(charPtr+1));
179 break;
180 case 'K':
181 SetupKillDimAreas(SkipSpacesTabs(charPtr+1));
182 break;
183 case 'L':
184 SetupLaplace();
185 break;
186 case 'N':
187 SearchCompareMode = NO_DC_SEARCH;
188 break;
189 case 'Q':
190 SearchCompareMode = DO_Mean_Squared_Distortion;
191 break;
192 case 'S':
193 SetupSquashSmall(SkipSpacesTabs(charPtr+1));
194 break;
195 case 'W':
196 SetupWriteDistortions(SkipSpacesTabs(charPtr+1));
197 break;
198 case 'U':
199 BSkipBlocks = FALSE;
200 break;
201 case 'Z':
202 IntraPBAllowed = FALSE;
203 break;
204 default:
205 fprintf(stderr, "Unknown tuning (%s) in parameter file.\n",charPtr);
206 break;
207 }
208 }
209
210
211 /*===============*
212 * Internals *
213 *===============*/
214
215 /*===========================================================================*
216 *
217 * SetupCollectQuantStats
218 *
219 * Setup variables to collect statistics on quantization values
220 *
221 * RETURNS: nothing
222 *
223 * SIDE EFFECTS: sets collect_quant and collect_quant_fp
224 *
225 *===========================================================================*/
226 void SetupCollectQuantStats(charPtr)
227 char *charPtr;
228 {
229 char fname[256], *cp;
230
231 cp = charPtr;
232 while ( (*cp != ' ') && (*cp != '\t') && (*cp != '\n')) {
233 cp++;
234 }
235
236 strncpy(fname, charPtr, cp-charPtr);
237 fname[cp-charPtr] = '\0';
238 collect_quant = TRUE;
239 if ((collect_quant_fp = fopen(fname,"w")) == NULL) {
240 fprintf(stderr, "Error opening %s for quant statistics\n", fname);
241 fprintf(stderr, "Using stdout (ick!)\n");
242 collect_quant_fp = stdout;
243 }
244
245 cp = SkipSpacesTabs(cp);
246 if (*cp != '\n') {
247 switch (*cp) {
248 case 'c':
249 collect_quant_detailed = 1;
250 break;
251 default:
252 fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp);
253 }}
254 }
255
256
257
258
259 /*===========================================================================*
260 *
261 * SetupKillDimAreas
262 *
263 * Do a transform on small lum values
264 *
265 * RETURNS: nothing
266 *
267 * SIDE EFFECTS: sets kill_dim, kill_dim_break, kill_dim_end
268 *
269 *===========================================================================*/
270 void SetupKillDimAreas(charPtr)
271 char *charPtr;
272 {
273 int items_scanned;
274
275 kill_dim = TRUE;
276 items_scanned = sscanf(charPtr, "%d %d %f",
277 &kill_dim_break, &kill_dim_end, &kill_dim_slope);
278 if (items_scanned != 3) {
279 kill_dim_slope = 0.25;
280 items_scanned = sscanf(charPtr, "%d %d",
281 &kill_dim_break, &kill_dim_end);
282 if (items_scanned != 2) {
283 /* Use defaults */
284 kill_dim_break = 20;
285 kill_dim_end = 25;
286 }
287 }
288 /* check values */
289 if (kill_dim_break > kill_dim_end) {
290 fprintf(stderr, "TUNE parameter k: break > end is illegal.\n");
291 exit(-1);
292 }
293 if (kill_dim_slope < 0) {
294 fprintf(stderr, "TUNE parameter k: slope < 0 is illegal.\n");
295 exit(-1);
296 }
297 }
298
299
300
301 /*===========================================================================*
302 *
303 * SetupSquashSmall
304 *
305 * Setup encoder to squash small changes in Y or Cr/Cb values
306 *
307 * RETURNS: nothing
308 *
309 * SIDE EFFECTS: sets squash_max_differences SquashMaxLum SquashMaxChr
310 *
311 *===========================================================================*/
312 void SetupSquashSmall(charPtr)
313 char *charPtr;
314 {
315 squash_small_differences = TRUE;
316
317 if (sscanf(charPtr, "%d %d", &SquashMaxLum, &SquashMaxChr) == 1) {
318 /* Only set one, do both */
319 SquashMaxChr = SquashMaxLum;
320 }
321 }
322
323
324 /*===========================================================================*
325 *
326 * SetupLocalDCT
327 *
328 * Setup encoder to use DCT for rate-distortion estimat ein Psearches
329 *
330 * RETURNS: nothing
331 *
332 * SIDE EFFECTS: sets SearchCompareMode and
333 * can change LocalDCTRateScale, LocalDCTDistortScale
334 *
335 *===========================================================================*/
336 void SetupLocalDCT(charPtr)
337 char *charPtr;
338 {
339 int num_scales=0;
340
341 SearchCompareMode = LOCAL_DCT;
342
343 /* Set scaling factors if present */
344 num_scales = sscanf(charPtr, "%f %f", &LocalDCTRateScale, &LocalDCTDistortScale);
345 if (num_scales == 1) {
346 fprintf(stderr, "Invalid number of scaling factors for local DCT\n");
347 fprintf(stderr, "Must specify Rate Scale and Distorion scale (both floats)\n");
348 fprintf(stderr, "Continuing with 1.0 1.0\n");
349 LocalDCTRateScale = 1.0;
350 LocalDCTDistortScale = 1.0;
351 }
352 }
353
354
355 /*===========================================================================*
356 *
357 * SetupLaplace
358 *
359 * Setup encoder to find distrubution for I-frames, and use for -snr
360 *
361 * RETURNS: nothing
362 *
363 * SIDE EFFECTS: sets DoLaplace, L1, L2, and Lambdas
364 *
365 *===========================================================================*/
366 void SetupLaplace()
367 {
368 int i;
369
370 DoLaplace = TRUE;
371 LaplaceNum = 0;
372 L1 = (double **)malloc(sizeof(double *)*3);
373 L2 = (double **)malloc(sizeof(double *)*3);
374 Lambdas = (double **)malloc(sizeof(double *)*3);
375 if (L1 == NULL || L2 == NULL || Lambdas == NULL) {
376 fprintf(stderr,"Out of memory!!!\n");
377 exit(1);
378 }
379 for (i = 0; i < 3; i++) {
380 L1[i] = (double *)calloc(64, sizeof(double));
381 L2[i] = (double *)calloc(64, sizeof(double));
382 Lambdas[i] = (double *)malloc(sizeof(double) * 64);
383 if (L1[i] == NULL || L2[i] == NULL || Lambdas[i] == NULL) {
384 fprintf(stderr,"Out of memory!!!\n");
385 exit(1);
386 }
387 }
388 }
389
390 void CalcLambdas()
391 {
392 int i,j,n;
393 double var;
394
395 n = LaplaceNum;
396 for (i = 0; i < 3; i++) {
397 for (j = 0; j < 64; j++) {
398 var = (n*L1[i][j] + L2[i][j]*L2[i][j]) / (n*(n-1));
399 Lambdas[i][j] = sqrt(2.0) / sqrt(var);
400 }
401 }
402 }
403
404
405 /*===========================================================================*
406 *
407 * Mpost_UnQuantZigBlockLaplace
408 *
409 * unquantize and zig-zag (decode) a single block, using the distrib to get vals
410 * Iblocks only now
411 *
412 * RETURNS: nothing
413 *
414 * SIDE EFFECTS: none
415 *
416 *===========================================================================*/
417 void
418 Mpost_UnQuantZigBlockLaplace(in, out, qscale, iblock)
419 FlatBlock in;
420 Block out;
421 int qscale;
422 boolean iblock;
423 {
424 register int index;
425 int position;
426 register int qentry;
427 int level, coeff;
428 double low, high;
429 double mid,lam;
430
431 /* qtable[0] must be 8 */
432 out[0][0] = (int16)(in[0] * 8);
433
434 for ( index = 1; index < DCTSIZE_SQ; index++ ) {
435 position = ZAG[index];
436 level = in[index];
437
438 if (level == 0) {
439 ((int16 *)out)[position] = 0;
440 continue;
441 }
442 qentry = qtable[position] * qscale;
443 coeff = (level*qentry)/8;
444 low = ((ABS(level)-.5)*qentry)/8;
445 high = ((ABS(level)+.5)*qentry)/8;
446 lam = Lambdas[LaplaceCnum][position];
447 mid = (1.0/lam) * log(0.5*(exp(-lam*low)+exp(-lam*high)));
448 mid = ABS(mid);
449 if (mid - floor(mid) > .4999) {
450 mid = ceil(mid);
451 } else {
452 mid = floor(mid);
453 }
454 if (level<0) {mid = -mid;}
455 /*printf("(%2.1lf-%2.1lf): old: %d vs %d\n",low,high,coeff,(int) mid);*/
456 coeff = mid;
457 if ( (coeff & 1) == 0 ) {
458 if ( coeff < 0 ) {
459 coeff++;
460 } else if ( coeff > 0 ) {
461 coeff--;
462 }
463 }
464 ((int16 *)out)[position] = coeff;
465 }
466 }
467
468 void
469 SetupWriteDistortions(charPtr)
470 char *charPtr;
471 {
472 char fname[256], *cp;
473 int i;
474
475 WriteDistortionNumbers = TRUE;
476 cp = charPtr;
477 while ( (*cp != ' ') && (*cp != '\t') && (*cp != '\n')) {
478 cp++;
479 }
480
481 strncpy(fname, charPtr, cp-charPtr);
482 fname[cp-charPtr] = '\0';
483 collect_quant = TRUE;
484 if ((distortion_fp = fopen(fname,"w")) == NULL) {
485 fprintf(stderr, "Error opening %s for quant statistics\n", fname);
486 fprintf(stderr, "Using stdout (ick!)\n");
487 distortion_fp = stdout;
488 }
489
490 cp = SkipSpacesTabs(cp);
491 if (*cp != '\n') {
492 switch (*cp) {
493 case 'c':
494 collect_distortion_detailed = TRUE;
495 break;
496 case 't': {
497 char scratch[256];
498 collect_distortion_detailed = 2;
499 for (i = 1; i < 32; i++) {
500 sprintf(scratch, "%srate%d", fname, i);
501 fp_table_rate[i-1] = fopen(scratch, "w");
502 sprintf(scratch, "%sdist%d", fname, i);
503 fp_table_dist[i-1] = fopen(scratch, "w");
504 }}
505 break;
506 default:
507 fprintf(stderr, "Unknown TUNE parameter setting format %s\n", cp);
508 }}
509 }
510
511 int mse(blk1, blk2)
512 Block blk1, blk2;
513 {
514 register int index, error, tmp;
515 int16 *bp1, *bp2;
516
517 bp1 = (int16 *)blk1;
518 bp2 = (int16 *)blk2;
519 error = 0;
520 for ( index = 0; index < DCTSIZE_SQ; index++ ) {
521 tmp = *bp1++ - *bp2++;
522 error += tmp*tmp;
523 }
524 return error;
525 }