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