Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * main.c --
3
 *
4
 *      Main procedure
5
 *
6
 */
7
 
8
/*
9
 * Copyright (c) 1995 The Regents of the University of California.
10
 * All rights reserved.
11
 *
12
 * Permission to use, copy, modify, and distribute this software and its
13
 * documentation for any purpose, without fee, and without written agreement is
14
 * hereby granted, provided that the above copyright notice and the following
15
 * two paragraphs appear in all copies of this software.
16
 *
17
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
18
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
19
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
20
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
 *
22
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
23
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
25
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
26
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
27
 */
28
 
29
/*
30
 * Portions of this software Copyright (c) 1995 Brown University.
31
 * All rights reserved.
32
 *
33
 * Permission to use, copy, modify, and distribute this software and its
34
 * documentation for any purpose, without fee, and without written agreement
35
 * is hereby granted, provided that the above copyright notice and the
36
 * following two paragraphs appear in all copies of this software.
37
 *
38
 * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
39
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
40
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
41
 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
 *
43
 * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
44
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
45
 * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
46
 * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
47
 * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
48
 */
49
 
50
#include "video.h"
51
#include "proto.h"
52
#ifndef NOCONTROLS
53
#include "ctrlbar.h"
54
#endif
55
#include <math.h>
56
#include <sys/types.h>
57
#include <signal.h>
58
#include <netinet/in.h>
59
#include <string.h> /* strtok */
60
#include "util.h"
61
#include "dither.h"
62
 
63
/*
64
   Changes to make the code reentrant:
65
     Got rid of setjmp, longjmp
66
     deglobalized: EOF_flag, FilmState, curVidStream, bitOffset, bitLength,
67
     bitBuffer, sys_layer, input, seekValue, window, X Windows globals (to
68
     xinfo), curBits, ditherType, matched_depth, totNumFrames, realTimeStart
69
 
70
   Additional changes:
71
     Ability to play >1 movie (w/out CONTROLS)
72
     Make sure we do a full frame for each movie
73
     DISABLE_DITHER #ifdef to avoid compiling dithering code
74
     Changes to deal with non-MPEG streams
75
     Now deals with NO_DITHER, PPM_DITHER and noDisplayFlag==1
76
     CONTROLS version now can deal with >1 movie
77
   -lsh@cs.brown.edu (Loring Holden)
78
 */
79
 
80
/* Make Ordered be the default dither */
81
#define DEFAULT_ORDERED_DITHER
82
 
83
/* Define buffer length. */
84
#define BUF_LENGTH 80000
85
 
86
/* Function return type declarations */
87
void usage();
88
 
89
/* Forward declaration of functions in this file. */
90
#ifndef P
91
# ifdef __STDC__
92
#   define        P(s) s
93
# else
94
#   define P(s) ()
95
# endif
96
#endif 
97
 
98
#ifndef SIG_ONE_PARAM
99
void int_handler P((void ));
100
void bad_handler P((void ));
101
#else
102
void int_handler P((int signum));
103
void bad_handler P((int signum));
104
#endif
105
void usage P((char *s ));
106
 
107
#ifdef DCPREC
108
/* Declaration of global variable to hold DC precision */
109
int dcprec = 0;
110
#endif
111
 
112
/* Global file pointer to incoming data. */
113
FILE **input;
114
char **inputName;
115
 
116
/* Loop flag. */
117
int loopFlag = 0;
118
 
119
/* Shared memory flag. */
120
int shmemFlag = 0;
121
 
122
/* Quiet flag. */
123
#ifdef QUIET
124
int quietFlag = 1;
125
#else
126
int quietFlag = 0;
127
#endif
128
 
129
/* "Press return" flag, requires return for each new frame */
130
int requireKeypressFlag = 0;
131
 
132
/* Display image on screen? */
133
int noDisplayFlag = 0;
134
 
135
/* Seek Value.
136
 
137
   N (N>0) means seek to N after the header is parsed
138
   N (N<0) means the seek has beeen done to offset N
139
*/
140
 
141
/* Framerate, -1: specified in stream (default)
142
               0: as fast as possible
143
               N (N>0): N frames/sec  
144
               */
145
int framerate = -1;
146
 
147
/* Flags/values to control Arbitrary start/stop frames. */
148
int partialFlag = 0, startFrame = -1, endFrame = -1;
149
 
150
/* Flag for gamma correction */
151
int gammaCorrectFlag = 0;
152
double gammaCorrect = 1.0;
153
 
154
/* Flag for chroma correction */
155
int chromaCorrectFlag = 0;
156
double chromaCorrect = 1.0;
157
 
158
/* Flag for high quality at the expense of speed */
159
#ifdef QUALITY
160
int qualityFlag = 1;
161
#else
162
int qualityFlag = 0;
163
#endif
164
 
165
/* no further error messages */
166
static BOOLEAN exiting=FALSE;
167
 
168
/* global variable for interrupt handlers */
169
VidStream **curVidStream;
170
 
171
/* Brown - put X specific variables in xinfo struct */
172
#define NUMMOVIES 15
173
XInfo xinfo[NUMMOVIES];
174
int numInput=0;
175
 
176
/*
177
 #define Color16DitherImage ColorDitherImage
178
 #define Color32DitherImage ColorDitherImage
179
*/
180
 
181
/*
182
 *--------------------------------------------------------------
183
 *
184
 * int_handler --
185
 *
186
 *        Handles Cntl-C interupts..
187
 *      (two different ones for different OSes)
188
 * Results:    None.
189
 * Side effects:   None.
190
 *--------------------------------------------------------------
191
 */
192
#ifndef SIG_ONE_PARAM
193
void
194
int_handler()
195
#else
196
void
197
int_handler(signum)
198
int signum;
199
#endif
200
{
201
  int i,displayClosed=0;
202
 
203
  if (!quietFlag && !exiting) {
204
    fprintf(stderr, "Interrupted!\n");
205
  }
206
  exiting = TRUE;
207
  for (i = 0;  i < numInput;  i++) {
208
    if (curVidStream[i] != NULL)
209
      DestroyVidStream(curVidStream[i], &xinfo[i]);
210
    if ((xinfo[i].display != NULL) && !displayClosed) {
211
      XCloseDisplay(xinfo[i].display);
212
      displayClosed=1;
213
    }
214
  }
215
  exit(1);
216
}
217
 
218
 
219
/*
220
 *--------------------------------------------------------------
221
 *
222
 * bad_handler --
223
 *
224
 *        Handles Seg faults/bus errors...
225
 *      (two different ones for different OSes)
226
 * Results:    None.
227
 * Side effects:   None.
228
 *
229
 *--------------------------------------------------------------
230
 */
231
 
232
#ifndef SIG_ONE_PARAM
233
void
234
  bad_handler()
235
#else
236
void
237
  bad_handler(signum)
238
int signum;
239
#endif
240
{
241
  if (!exiting) {
242
    fprintf(stderr, "Bad MPEG?  Giving up.\ntry 'mpeg_stat -verify' to see if the stream is valid.\n");
243
  }
244
  exit(0);
245
}
246
 
247
 
248
/*
249
 *--------------------------------------------------------------
250
 *
251
 * getposition --
252
 *
253
 *--------------------------------------------------------------
254
 */
255
void getposition(arg, xpos, ypos)
256
char *arg;
257
int *xpos, *ypos;
258
{
259
  char *pos;
260
 
261
  if ((pos = strtok(arg, "+-")) != NULL) {
262
    *xpos = atoi(pos);
263
    if ((pos = strtok(NULL, "+-")) != NULL) {
264
      *ypos = atoi(pos);
265
      return;
266
    }
267
  }
268
  if (!quietFlag) {
269
    fprintf(stderr, "Illegal position... Warning: argument ignored! (-position +x+y)\n");
270
  }
271
  return;
272
}
273
 
274
 
275
/*
276
 *--------------------------------------------------------------
277
 *
278
 * main --
279
 *
280
 *        Parses command line, starts decoding and displaying.
281
 *
282
 * Results:
283
 *        None.
284
 *
285
 * Side effects:
286
 *        None.
287
 *
288
 *--------------------------------------------------------------
289
 */
290
 
291
#ifndef __STDC__
292
void
293
#endif
294
main(argc, argv)
295
     int argc;
296
     char **argv;
297
{
298
 
299
  char *name;
300
  static VidStream **theStream;
301
  int mark;
302
  int i, mult, largy, y, lastStream, firstStream=-1, workToDo=TRUE;
303
  int doDisplay=0; /* Current movie is displaying on screen */
304
  long seekValue=0;/* holds value before it is put in vid_stream */
305
  int  owncmFlag=0;   /* holds value before it is put in xinfo  */
306
  BOOLEAN firstRead=FALSE;
307
  int ppm_width = -1,  ppm_height = -1, ppm_modulus = -1;
308
 
309
  mark = 1;
310
  argc--;
311
 
312
  input = (FILE **) malloc(NUMMOVIES*sizeof(FILE *));
313
  inputName = (char **) malloc(NUMMOVIES *sizeof(char *));
314
  theStream = (VidStream **) malloc(NUMMOVIES *sizeof(VidStream *));
315
  curVidStream = (VidStream **) malloc(NUMMOVIES *sizeof(VidStream *));
316
  for (i = 0; i < NUMMOVIES; i++) {
317
     input[i] = NULL;
318
     inputName[i] = "stdin";
319
     theStream[i] = NULL;
320
     curVidStream[i] = NULL;
321
     xinfo[i].hints.x = -1;
322
     xinfo[i].hints.y = -1;
323
     xinfo[i].ExistingWindow = 0;
324
  }
325
  name = (char *) "";
326
 
327
#ifndef DISABLE_DITHER
328
#ifndef DEFAULT_ORDERED_DITHER
329
  xinfo[0].ditherType = FULL_COLOR_DITHER;
330
#else
331
  xinfo[0].ditherType = ORDERED_DITHER;
332
#endif
333
#endif
334
 
335
  LUM_RANGE = 8;
336
  CR_RANGE = CB_RANGE = 4;
337
  noDisplayFlag = 0;
338
 
339
#ifdef SH_MEM
340
  shmemFlag = 1;
341
#endif
342
 
343
  while (argc) {
344
    if (strcmp(argv[mark], "-nop") == 0) {
345
      SetPFlag(TRUE);
346
      SetBFlag(TRUE);
347
      argc--; mark++;
348
    } else if (strcmp(argv[mark], "-nob") == 0) {
349
      SetBFlag(TRUE);
350
      argc--; mark++;
351
    } else if (strcmp(argv[mark], "-display") == 0) {
352
      name = argv[++mark];
353
      argc -= 2; mark++;
354
    } else if (strcmp(argv[mark], "-position") == 0) {
355
      argc--; mark++;
356
      getposition(argv[mark], &xinfo[numInput].hints.x, &xinfo[numInput].hints.y);
357
      argc--; mark++;
358
    } else if (strcmp(argv[mark], "-xid") == 0) {
359
      xinfo[numInput].ExistingWindow = atoi(argv[++mark]);
360
      argc -= 2; mark++;
361
    } else if (strcmp(argv[mark], "-start") == 0) {
362
      if (argc < 2) usage(argv[0]);
363
      partialFlag = TRUE;
364
      if (seekValue != 0) {
365
        fprintf(stderr, "Cannot use -start with -seek (ignored)\n");
366
      } else {
367
        startFrame = atoi(argv[++mark]);
368
      }
369
      argc -= 2; mark++;
370
    } else if (strcmp(argv[mark], "-seek") == 0) {
371
      if (argc < 2) usage(argv[0]);
372
      seekValue = atoi(argv[++mark]);
373
      if (startFrame != -1) startFrame = 0;
374
      argc -= 2; mark++;
375
    } else if (strcmp(argv[mark], "-end") == 0) {
376
      if (argc < 2) usage(argv[0]);
377
      endFrame = atoi(argv[++mark]);
378
      partialFlag = TRUE;
379
      argc -= 2; mark++;
380
    } else if (strcmp(argv[mark], "-gamma") == 0) {
381
      if (argc < 2) usage(argv[0]);
382
      gammaCorrectFlag = 1;
383
      sscanf(argv[++mark], "%lf", &gammaCorrect);
384
      if (gammaCorrect <= 0.0) {
385
        fprintf(stderr, "ERROR: Gamma correction must be greater than 0.\n");
386
        gammaCorrect = 1.0;
387
      }
388
      if (!quietFlag) {
389
        printf("Gamma Correction set to %4.2f.\n", gammaCorrect);
390
      }
391
      argc -= 2; mark++;
392
    } else if (strcmp(argv[mark], "-chroma") == 0) {
393
      if (argc < 2) usage(argv[0]);
394
      chromaCorrectFlag = 1;
395
      sscanf(argv[++mark], "%lf", &chromaCorrect);
396
      if (chromaCorrect <= 0.0) {
397
        fprintf(stderr, "ERROR: Chroma correction must be greater than 0.\n");
398
        chromaCorrect = 1.0;
399
      }
400
      if (!quietFlag) {
401
        printf("Chroma Correction set to %4.2f.\n",chromaCorrect);
402
      }
403
      argc -= 2; mark++;
404
#ifdef DCPREC
405
    } else if (strcmp(argv[mark], "-dc") == 0) {
406
      argc--; mark++;
407
      if (argc < 1) {
408
        perror("Must specify dc precision after -dc flag");
409
        usage(argv[0]);
410
      }
411
      dcprec = atoi(argv[mark]) - 8;
412
      if ((dcprec > 3) || (dcprec < 0)) {
413
        perror("DC precision must be at least 8 and at most 11");
414
        usage(argv[0]);
415
      }
416
      argc--; mark++;
417
#endif
418
    } else if (strcmp(argv[mark], "-quality") == 0) {
419
      argc--; mark++;
420
      if (argc < 1) {
421
        perror("Must specify on or off after -quality flag");
422
        usage(argv[0]);
423
      }
424
      if (strcmp(argv[mark], "on") == 0) {
425
        argc--; mark++;
426
        qualityFlag = 1;
427
      }
428
      else if (strcmp(argv[mark], "off") == 0) {
429
        argc--; mark++;
430
        qualityFlag = 0;
431
      }
432
      else {
433
        perror("Must specify on or off after -quality flag");
434
        usage(argv[0]);
435
      }
436
    } else if (strcmp(argv[mark], "-framerate") == 0) {
437
      argc--; mark++;
438
      if (argc < 1) {
439
        perror("Must specify framerate after -framerate flag");
440
        usage(argv[0]);
441
      }
442
      framerate = atoi(argv[mark]);
443
      argc--; mark++;
444
    } else if (strcmp(argv[mark], "-ppmwidth") == 0) {
445
      argc--; mark++;
446
      if (argc < 1) {
447
        perror("Must specify PPM file width after -ppmwidth flag");
448
        usage(argv[0]);
449
      }
450
      ppm_width = atoi(argv[mark]);
451
      argc--; mark++;
452
    } else if (strcmp(argv[mark], "-ppmheight") == 0) {
453
      argc--; mark++;
454
      if (argc < 1) {
455
        perror("Must specify PPM file height after -ppmheight flag");
456
        usage(argv[0]);
457
      }
458
      ppm_height = atoi(argv[mark]);
459
      argc--; mark++;
460
    } else if (strcmp(argv[mark], "-ppmskip") == 0) {
461
      argc--; mark++;
462
      if (argc < 1) {
463
        perror("Must specify PPM file height after -ppmheight flag");
464
        usage(argv[0]);
465
      }
466
      ppm_modulus = atoi(argv[mark]);
467
      argc--; mark++;
468
#ifndef DISABLE_DITHER
469
    } else if (strcmp(argv[mark], "-dither") == 0) {
470
      argc--; mark++;
471
      if (argc < 1) {
472
        perror("Must specify dither option after -dither flag");
473
        usage(argv[0]);
474
      }
475
      if (strcmp(argv[mark], "hybrid") == 0) {
476
        argc--; mark++;
477
        xinfo[0].ditherType = HYBRID_DITHER;
478
      } else if (strcmp(argv[mark], "hybrid2") == 0) {
479
        argc--; mark++;
480
        xinfo[0].ditherType = HYBRID2_DITHER;
481
      } else if (strcmp(argv[mark], "fs4") == 0) {
482
        argc--; mark++;
483
        xinfo[0].ditherType = FS4_DITHER;
484
      } else if (strcmp(argv[mark], "fs2") == 0) {
485
        argc--; mark++;
486
        xinfo[0].ditherType = FS2_DITHER;
487
      } else if (strcmp(argv[mark], "fs2fast") == 0) {
488
        argc--; mark++;
489
        xinfo[0].ditherType = FS2FAST_DITHER;
490
      } else if (strcmp(argv[mark], "hybrid2") == 0) {
491
        argc--; mark++;
492
        xinfo[0].ditherType = HYBRID2_DITHER;
493
      } else if (strcmp(argv[mark], "2x2") == 0) {
494
        argc--; mark++;
495
        xinfo[0].ditherType = Twox2_DITHER;
496
      } else if ((strcmp(argv[mark], "gray256") == 0) ||
497
                 (strcmp(argv[mark], "grey256") == 0)) {
498
        argc--; mark++;
499
        xinfo[0].ditherType = GRAY256_DITHER;
500
      } else if ((strcmp(argv[mark], "gray") == 0) ||
501
                 (strcmp(argv[mark], "grey") == 0)) {
502
        argc--; mark++;
503
        xinfo[0].ditherType = GRAY_DITHER;
504
      } else if ((strcmp(argv[mark], "gray256x2") == 0) ||
505
                  (strcmp(argv[mark], "grey256x2") == 0)) {
506
        argc--; mark++;
507
        xinfo[0].ditherType = GRAY2562_DITHER;
508
      } else if ((strcmp(argv[mark], "gray") == 0) ||
509
                   (strcmp(argv[mark], "grey") == 0)) {
510
        argc--; mark++;
511
        xinfo[0].ditherType = GRAY_DITHER;
512
      } else if ((strcmp(argv[mark], "gray2") == 0) ||
513
                  (strcmp(argv[mark], "grey2") == 0)) {
514
        argc--; mark++;
515
        xinfo[0].ditherType = GRAY2_DITHER;
516
      } else if (strcmp(argv[mark], "color") == 0 ||
517
                 strcmp(argv[mark], "colour") == 0) {
518
        argc--; mark++;
519
        xinfo[0].ditherType = FULL_COLOR_DITHER;
520
      } else if (strcmp(argv[mark], "color2") == 0 ||
521
                 strcmp(argv[mark], "colour2") == 0) {
522
        argc--; mark++;
523
        xinfo[0].ditherType = FULL_COLOR2_DITHER;
524
      } else if (strcmp(argv[mark], "none") == 0) {
525
        argc--; mark++;
526
        xinfo[0].ditherType = NO_DITHER;
527
      } else if (strcmp(argv[mark], "ppm") == 0) {
528
        argc--; mark++;
529
        xinfo[0].ditherType = PPM_DITHER;
530
      } else if (strcmp(argv[mark], "ordered") == 0) {
531
        argc--; mark++;
532
        xinfo[0].ditherType = ORDERED_DITHER;
533
      } else if (strcmp(argv[mark], "ordered2") == 0) {
534
        argc--; mark++;
535
        xinfo[0].ditherType = ORDERED2_DITHER;
536
      } else if (strcmp(argv[mark], "mbordered") == 0) {
537
        argc--; mark++;
538
        xinfo[0].ditherType = MBORDERED_DITHER;
539
      } else if (strcmp(argv[mark], "mono") == 0) {
540
        argc--; mark++;
541
        xinfo[0].ditherType = MONO_DITHER;
542
      } else if (strcmp(argv[mark], "threshold") == 0) {
543
        argc--; mark++;
544
        xinfo[0].ditherType = MONO_THRESHOLD;
545
      } else {
546
        perror("Illegal dither option.");
547
        usage(argv[0]);
548
      }
549
#endif
550
    }
551
    else if (strcmp(argv[mark], "-eachstat") == 0) {
552
      argc--; mark++;
553
#ifdef ANALYSIS
554
      showEachFlag = 1;
555
#else
556
      fprintf(stderr, "To use -eachstat, recompile with -DANALYSIS in CFLAGS\n");
557
      exit(1);
558
#endif
559
    }
560
    else if (strcmp(argv[mark], "-shmem_off") == 0) {
561
      argc--; mark++;
562
      shmemFlag = 0;
563
    }
564
#ifdef QUIET
565
    else if (strcmp(argv[mark], "-quiet") == 0) {
566
      argc--; mark++;
567
    }
568
    else if (strcmp(argv[mark], "-noisy") == 0) {
569
#else
570
    else if (strcmp(argv[mark], "-noisy") == 0) {
571
      argc--; mark++;
572
    }
573
    else if (strcmp(argv[mark], "-quiet") == 0) {
574
#endif
575
      argc--; mark++;
576
      quietFlag = !quietFlag;
577
    }
578
    else if (strcmp(argv[mark], "-owncm") == 0) {
579
      argc--; mark++;
580
      owncmFlag = 1;
581
    }
582
    else if (strcmp(argv[mark], "-step") == 0) {
583
      argc--; mark++;
584
      requireKeypressFlag = 1;
585
    }
586
    else if (strcmp(argv[mark], "-loop") == 0) {
587
      argc--; mark++;
588
      loopFlag = 1;
589
    }
590
    else if (strcmp(argv[mark], "-no_display") == 0) {
591
      argc--; mark++;
592
      noDisplayFlag = 1;
593
      shmemFlag = 0;
594
    }
595
    else if (strcmp(argv[mark], "-l_range") == 0) {
596
      argc--; mark++;
597
      LUM_RANGE = atoi(argv[mark]);
598
      if (LUM_RANGE < 1) {
599
        fprintf(stderr, "Illegal luminance range value: %d\n", LUM_RANGE);
600
        exit(1);
601
      }
602
      argc--; mark++;
603
    }
604
    else if (strcmp(argv[mark], "-cr_range") == 0) {
605
      argc--; mark++;
606
      CR_RANGE = atoi(argv[mark]);
607
      if (CR_RANGE < 1) {
608
        fprintf(stderr, "Illegal cr range value: %d\n", CR_RANGE);
609
        exit(1);
610
      }
611
      argc--; mark++;
612
    }
613
    else if (strcmp(argv[mark], "-cb_range") == 0) {
614
      argc--; mark++;
615
      CB_RANGE = atoi(argv[mark]);
616
      if (CB_RANGE < 1) {
617
        fprintf(stderr, "Illegal cb range value: %d\n", CB_RANGE);
618
        exit(1);
619
      }
620
      argc--; mark++;
621
    }
622
#ifndef NOCONTROLS
623
    else if (strcmp(argv[mark], "-controls") == 0 ||
624
             strcmp(argv[mark], "-controlbar") == 0 ||
625
             strcmp(argv[mark], "-control_bar") == 0) {
626
      argc--; mark++;
627
      if (argc < 1) {
628
        perror("Must specify on, off, or none after -controls flag");
629
        usage(argv[0]);
630
      }
631
      if (strcmp(argv[mark], "on") == 0) {
632
        argc--; mark++;
633
        ControlShow = CTRLBAR_ON;
634
      }
635
      else if (strcmp(argv[mark], "off") == 0) {
636
        argc--; mark++;
637
        ControlShow = CTRLBAR_OFF;
638
      }
639
      else if (strcmp(argv[mark], "none") == 0) {
640
        argc--; mark++;
641
        ControlShow = CTRLBAR_NONE;
642
      }
643
      else {
644
        perror("Must specify on, off, or none after -controls flag");
645
        usage(argv[0]);
646
      }
647
    }
648
#endif /* !NOCONTROLS */
649
    else if ((strcmp(argv[mark], "-?") == 0) ||
650
               (strcmp(argv[mark], "-Help") == 0) ||
651
               (strcmp(argv[mark], "-help") == 0)) {
652
      usage(argv[0]);
653
    }
654
    else if (argv[mark][0] == '-' && argv[mark][1]==0) {
655
      fflush(stdout);
656
      if (numInput<NUMMOVIES) {
657
        input[numInput]=stdin;
658
        inputName[numInput++] = "stdin";
659
      } else {
660
          fprintf(stderr, "Can't load file %s - too many\n", "stdin");
661
      }
662
      argc--; mark++;
663
    }
664
    else if (argv[mark][0] == '-') {
665
      fprintf(stderr, "Un-recognized flag %s\n",argv[mark]);
666
      usage(argv[0]);
667
    }
668
    else {
669
      fflush(stdout);
670
      if (numInput<NUMMOVIES) {
671
        input[numInput]=fopen(argv[mark], "r");
672
        if (input[numInput] == NULL) {
673
          fprintf(stderr, "Could not open file %s\n", argv[mark]);
674
          usage(argv[0]);
675
        }
676
        inputName[numInput++] = argv[mark];
677
      } else {
678
          fprintf(stderr, "Can't load file %s - too many\n", argv[mark]);
679
      }
680
      argc--; mark++;
681
    }
682
  }
683
 
684
  lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
685
  cr_values = (int *) malloc(CR_RANGE*sizeof(int));
686
  cb_values = (int *) malloc(CB_RANGE*sizeof(int));
687
 
688
  signal(SIGINT, int_handler);
689
#ifndef DEBUG
690
  signal(SIGSEGV, bad_handler);
691
  signal(SIGBUS,  bad_handler);
692
#endif
693
  if ((startFrame != -1) && (endFrame != -1) &&
694
      (endFrame < startFrame)) {
695
    usage(argv[0]);
696
  }
697
 
698
  init_tables();
699
  for (i = 0;  i < numInput;  i++) {
700
    xinfo[i].owncmFlag = owncmFlag;
701
    xinfo[i].display = NULL;       /* xinfo.ximage is set to null later */
702
    if (xinfo[i].hints.x == -1) {
703
      xinfo[i].hints.x = 200;
704
      xinfo[i].hints.y = 300;
705
    }
706
    xinfo[i].hints.width = 150;
707
    xinfo[i].hints.height = 150;
708
    xinfo[i].visual = NULL;
709
    xinfo[i].name = inputName[i];
710
    xinfo[i].cmap = 0;
711
    xinfo[i].gc = 0;
712
  }
713
 
714
#ifndef DISABLE_DITHER
715
  if (xinfo[0].ditherType == MONO_DITHER ||
716
      xinfo[0].ditherType == MONO_THRESHOLD)
717
    xinfo[0].depth= 1;
718
 
719
  switch (xinfo[0].ditherType) {
720
 
721
  case HYBRID_DITHER:
722
    InitColor();
723
    InitHybridDither();
724
    InitDisplay(name, &xinfo[0]);
725
    break;
726
 
727
  case HYBRID2_DITHER:
728
    InitColor();
729
    InitHybridErrorDither();
730
    InitDisplay(name, &xinfo[0]);
731
    break;
732
 
733
  case FS4_DITHER:
734
    InitColor();
735
    InitFS4Dither();
736
      InitDisplay(name, &xinfo[0]);
737
    break;
738
 
739
  case FS2_DITHER:
740
    InitColor();
741
    InitFS2Dither();
742
    InitDisplay(name, &xinfo[0]);
743
    break;
744
 
745
  case FS2FAST_DITHER:
746
    InitColor();
747
    InitFS2FastDither();
748
    InitDisplay(name, &xinfo[0]);
749
    break;
750
 
751
  case Twox2_DITHER:
752
    InitColor();
753
    Init2x2Dither();
754
    InitDisplay(name, &xinfo[0]);
755
    PostInit2x2Dither();
756
    break;
757
 
758
  case GRAY_DITHER:
759
  case GRAY2_DITHER:
760
    InitGrayDisplay(name, &xinfo[0]);
761
    break;
762
 
763
  case GRAY256_DITHER:
764
  case GRAY2562_DITHER:
765
    InitGray256Display(name, &xinfo[0]);
766
    break;
767
 
768
  case FULL_COLOR_DITHER:
769
  case FULL_COLOR2_DITHER:
770
    InitColorDisplay(name, &xinfo[0]);
771
    InitColorDither(xinfo[0].depth>=24);
772
#else
773
    InitColorDisplay(name, &xinfo[0]);
774
    InitColorDither(xinfo[0].depth>=24);
775
#endif
776
#ifndef DISABLE_DITHER
777
    break;
778
 
779
  case NO_DITHER:
780
    shmemFlag = 0;
781
    break;
782
 
783
  case PPM_DITHER:
784
    shmemFlag = 0;
785
    wpixel[0] = 0xff;
786
    wpixel[1] = 0xff00;
787
    wpixel[2] = 0xff0000;
788
    xinfo[0].depth = 24;
789
    InitColorDither(1);
790
    break;
791
 
792
  case ORDERED_DITHER:
793
    InitColor();
794
    InitOrderedDither();
795
    InitDisplay(name, &xinfo[0]);
796
    break;
797
 
798
  case MONO_DITHER:
799
  case MONO_THRESHOLD:
800
    InitMonoDisplay(name, &xinfo[0]);
801
    break;
802
 
803
  case ORDERED2_DITHER:
804
    InitColor();
805
    InitDisplay(name, &xinfo[0]);
806
    InitOrdered2Dither();
807
    break;
808
 
809
  case MBORDERED_DITHER:
810
    InitColor();
811
    InitDisplay(name, &xinfo[0]);
812
    InitMBOrderedDither();
813
    break;
814
  }
815
#endif
816
 
817
#ifdef SH_MEM
818
    if (shmemFlag && (xinfo[0].display != NULL)) {
819
      if (!XShmQueryExtension(xinfo[0].display)) {
820
        shmemFlag = 0;
821
        if (!quietFlag) {
822
          fprintf(stderr, "Shared memory not supported\n");
823
          fprintf(stderr, "Reverting to normal Xlib.\n");
824
        }
825
      }
826
    }
827
#endif
828
 
829
  InitCrop();
830
 
831
  y=300;
832
  largy=0;
833
  for (i=0;i<numInput;i++) {
834
    doDisplay=!noDisplayFlag;
835
#ifndef DISABLE_DITHER
836
    if ((xinfo[i].ditherType == NO_DITHER) ||
837
        (xinfo[i].ditherType == PPM_DITHER))
838
       doDisplay = FALSE;
839
#endif
840
    lastStream = i-1;
841
    while ((lastStream>=0) && (theStream[lastStream]==NULL)) {
842
       lastStream--;
843
    }
844
    if ((i != 0) && doDisplay) {
845
       if (lastStream > -1) {
846
         xinfo[i].hints.x =
847
            xinfo[lastStream].hints.x+10 + theStream[lastStream]->h_size;
848
         if (theStream[lastStream]->v_size>largy)
849
           largy = theStream[lastStream]->v_size;
850
         if (xinfo[i].hints.x > DisplayWidth(xinfo[firstStream].display,
851
                               XDefaultScreen(xinfo[firstStream].display)) -80) {
852
 
853
                y += largy + 30;
854
                largy = 0;
855
                xinfo[i].hints.x = 0;
856
         }
857
         xinfo[i].hints.y = y;
858
         xinfo[i].visual = xinfo[firstStream].visual;
859
         xinfo[i].cmap = xinfo[firstStream].cmap;
860
         xinfo[i].gc = xinfo[firstStream].gc;
861
       }
862
       xinfo[i].display = xinfo[0].display;
863
       xinfo[i].depth = xinfo[0].depth;
864
       xinfo[i].ditherType = xinfo[0].ditherType;
865
       InitColorDisplay(name, &xinfo[i]);
866
    }
867
    curVidStream[i] = theStream[i] = NewVidStream((unsigned int) BUF_LENGTH);
868
    theStream[i]->ppm_width = ppm_width;
869
    theStream[i]->ppm_height = ppm_height;
870
    theStream[i]->ppm_modulus = ppm_modulus;
871
    theStream[i]->input = input[i];
872
    theStream[i]->seekValue = seekValue;
873
    theStream[i]->filename = inputName[i];
874
    theStream[i]->ditherType = xinfo[i].ditherType;
875
    theStream[i]->matched_depth = xinfo[i].depth;
876
    mark = quietFlag;
877
    quietFlag=1;
878
    if (mpegVidRsrc(0, theStream[i], 1, &xinfo[i])==NULL) {
879
       if (doDisplay) {
880
         XDestroyWindow(xinfo[i].display, xinfo[i].window);
881
       }         
882
       /* stream has already been destroyed */
883
       curVidStream[i] = theStream[i]=NULL;
884
       fprintf(stderr, "Skipping movie %d, \"%s\" - not an MPEG stream\n",
885
          i, inputName[i]);
886
       fclose(input[i]);
887
       if (i+1 == numInput) numInput--;
888
    } else if (firstStream == -1) firstStream=i;
889
    quietFlag = mark;
890
 
891
#ifndef DISABLE_DITHER
892
    if (IS_2x2_DITHER(xinfo[i].ditherType)) {
893
      mult = 2;
894
    }
895
    else {
896
      mult = 1;  
897
    }
898
#else
899
    mult = 1;
900
#endif
901
 
902
    if (doDisplay && (theStream[i]!=NULL)) {
903
      ResizeDisplay((unsigned int) theStream[i]->h_size* mult,
904
                    (unsigned int) theStream[i]->v_size* mult,
905
                  &xinfo[i]);
906
    }
907
  }
908
 
909
  if (numInput > 1) {
910
    loopFlag = TRUE;
911
    framerate = 0;
912
  }
913
 
914
#ifndef NOCONTROLS
915
  if (xinfo[0].display == NULL) {
916
    ControlShow = CTRLBAR_NONE;  /* no display => no controls */
917
  }
918
 
919
  if (ControlShow != CTRLBAR_NONE) {
920
    MakeControlBar(&xinfo[0]);
921
    ControlBar(theStream, xinfo, numInput);
922
  }
923
  for (i = 0; i < numInput; i++) {
924
     if (theStream[i] != NULL) theStream[i]->realTimeStart = ReadSysClock();
925
  }
926
#else
927
  /* Start time for each movie - do after windows are mapped */
928
  for (i = 0; i < numInput; i++) {
929
     if (theStream[i] != NULL) theStream[i]->realTimeStart = ReadSysClock();
930
  }
931
#endif
932
 
933
 
934
#ifndef NOCONTROLS
935
  if (ControlShow == CTRLBAR_NONE) {
936
    while (TRUE) {
937
      for (i=0;i < numInput; i++) {
938
        while (theStream[i]->film_has_ended != TRUE) {
939
          mpegVidRsrc(0, theStream[i], 0, &xinfo[i]);
940
        }
941
        if (loopFlag) {
942
          rewind(theStream[i]->input);
943
          ResetVidStream(theStream[i]); /* Reinitialize vid_stream pointers */
944
          if (theStream[i]->seekValue < 0) {
945
            theStream[i]->seekValue = 0 - theStream[i]->seekValue;
946
          }
947
          mpegVidRsrc(0, theStream[i], 1, &xinfo[i]); /* Process start codes */
948
        } else if (doDisplay) break;
949
        else goto done;
950
      }
951
     }
952
   }
953
  else {
954
    ControlLoop(theStream, xinfo, numInput);
955
  }
956
 
957
done:
958
  mark=0;
959
  for (i=0;i < numInput; i++) {
960
    DestroyVidStream(theStream[i], &xinfo[i]);
961
    if ((xinfo[i].display != NULL) && !mark) {
962
      XCloseDisplay(xinfo[i].display);
963
      mark=1;
964
    }
965
  }
966
  exit(0);
967
#else /* !NOCONTROLS */
968
  if (!numInput) {
969
     fprintf(stderr, "Must enter MPEG file to play\n");
970
     usage(argv[0]);
971
  }
972
  while (workToDo) {
973
     workToDo = FALSE;
974
     for (i = 0; i < numInput; i++) {
975
       if (theStream[i] != NULL) {
976
         mark = theStream[i]->totNumFrames;
977
         /* make sure we do a whole frame */
978
         while (mark == theStream[i]->totNumFrames) {
979
             mpegVidRsrc(0, theStream[i], 0, &xinfo[i]);
980
         }
981
         if (theStream[i]->film_has_ended) {
982
           if (loopFlag) {
983
             clear_data_stream(theStream[i]);
984
             /* Reinitialize vid_stream pointers */
985
             ResetVidStream(theStream[i]);
986
             rewind(theStream[i]->input);
987
             if (theStream[i]->seekValue < 0) {
988
               theStream[i]->seekValue = 0 - theStream[i]->seekValue;
989
             }
990
#ifdef ANALYSIS 
991
             init_stats();
992
#endif
993
             /* Process start codes */
994
             if (mpegVidRsrc(0, theStream[i], 1, &xinfo[i])==NULL) {
995
               /* print something sensible here,
996
                  but we only get here if the file is changed while we
997
                  are decoding, right?
998
                */
999
             }
1000
           } /* loopFlag */
1001
         }   /* film_has_ended */
1002
         workToDo = workToDo || (!theStream[i]->film_has_ended);
1003
       } /* theStream[i]!=NULL */
1004
     }   /* for (i.. */
1005
  }      /* while workToDo */
1006
  sleep(1000);
1007
    /* freeze on the last frame */
1008
#endif /* NOCONTROLS */
1009
}
1010
 
1011
 
1012
/*
1013
 *--------------------------------------------------------------
1014
 *
1015
 * usage --
1016
 *
1017
 *        Print mpeg_play usage
1018
 *
1019
 * Results:
1020
 *        None.
1021
 *
1022
 * Side effects:
1023
 *        exits with a return value -1
1024
 *
1025
 *--------------------------------------------------------------
1026
 */
1027
 
1028
void
1029
usage(s)
1030
char *s;        /* program name */
1031
{
1032
    fprintf(stderr, "Usage:\n");
1033
#ifndef NOCONTROLS
1034
    fprintf(stderr, "mpeg_play [options] [filename]\n");
1035
#else
1036
    fprintf(stderr, "mpeg_play [[options] [filename]]  [[options] [filename]]  [..]\n");
1037
#endif
1038
    fprintf(stderr, "Options :\n");
1039
   fprintf(stderr, "      [-display X_display]\t[-no_display]\n");
1040
#ifndef DISABLE_DITHER
1041
    fprintf(stderr, "      [-dither {ordered|ordered2|mbordered|fs4|fs2|fs2fast|hybrid|\n");
1042
    fprintf(stderr, "                hybrid2|2x2|gray|gray256|color|color2|none|mono|threshold|ppm|\n");
1043
    fprintf(stderr, "                gray2|gray256x2}]\n");
1044
#endif
1045
    fprintf(stderr, "      [-loop]\n");
1046
    fprintf(stderr, "      [-start frame_num]\t[-end frame_num]\t[-seek file_offset]\n");
1047
    fprintf(stderr, "      [-gamma gamma_correction_value]\t[-chroma chroma_correction_value]\n");
1048
    fprintf(stderr, "      [-framerate num_frames_per_sec]  (0 means as fast as possible)\n");
1049
    fprintf(stderr, "      [-position +x+y]\t[-quality {on|off}] (compiled default is ");
1050
#ifdef QUALITY
1051
    fprintf(stderr, "ON)\n");
1052
#else
1053
    fprintf(stderr, "OFF)\n");
1054
#endif
1055
#ifdef QUIET
1056
    fprintf(stderr, "      [-noisy] (turns on all program output)\n");
1057
#else
1058
    fprintf(stderr, "      [-quiet] (turns off all program output)\n");
1059
#endif
1060
#ifndef NOCONTROLS
1061
    fprintf(stderr, "      [-controls {on|off|none}] (default is on)\n");
1062
#endif
1063
    fprintf(stderr, "      [-?]\t[-help] for help (this message)\n");
1064
    fprintf(stderr, "Rare options:\n");
1065
    fprintf(stderr, "      [-nob]\t[-nop]\n");
1066
#ifdef ANALYSIS
1067
    fprintf(stderr, "      [-eachstat]\t[-owncm]\t[-shmem_off]\n");
1068
#else
1069
    fprintf(stderr, "      [-owncm]\t[-shmem_off]\n");
1070
#endif
1071
    fprintf(stderr, "      [-l_range num]\t[-cr_range num]\t[-cb_range num]\n");
1072
/*    fprintf(stderr, "      [-xid xid]\n"); */
1073
#ifdef DCPREC
1074
    fprintf(stderr, "      [-dc {8|9|10|11}] (defaults to 8)\n");
1075
#endif
1076
    fprintf(stderr, "      with -dither ppm:\n");
1077
    fprintf(stderr, "          [-ppmwidth num]\t[-ppmheight num]\t[-ppmskip num]\n");
1078
    exit (-1);
1079
}
1080
 
1081
 
1082
 
1083
/*
1084
 *--------------------------------------------------------------
1085
 *
1086
 * DoDitherImage --
1087
 *
1088
 *      Called when image needs to be dithered. Selects correct
1089
 *      dither routine based on info in xinfo[0].ditherType.
1090
 *
1091
 * Results:
1092
 *        None.
1093
 *
1094
 * Side effects:
1095
 *        None.
1096
 *
1097
 *--------------------------------------------------------------
1098
 */
1099
 
1100
void
1101
DoDitherImage(vid_stream)
1102
VidStream *vid_stream;
1103
{
1104
 unsigned char *l=vid_stream->current->luminance,
1105
               *Cr=vid_stream->current->Cr,
1106
               *Cb=vid_stream->current->Cb,
1107
               *disp=vid_stream->current->display;
1108
 int h=(int) vid_stream->mb_height * 16;
1109
 int w=(int) vid_stream->mb_width * 16;
1110
 int ditherType=vid_stream->ditherType;
1111
 int matched_depth=vid_stream->matched_depth;
1112
 
1113
#ifndef DISABLE_DITHER
1114
  switch(ditherType) {
1115
  case HYBRID_DITHER:
1116
    HybridDitherImage(l, Cr, Cb, disp, h, w);
1117
    break;
1118
 
1119
  case HYBRID2_DITHER:
1120
    HybridErrorDitherImage(l, Cr, Cb, disp, h, w);
1121
    break;
1122
 
1123
  case FS2FAST_DITHER:
1124
    FS2FastDitherImage(l, Cr, Cb, disp, h, w);
1125
    break;
1126
 
1127
  case FS2_DITHER:
1128
    FS2DitherImage(l, Cr, Cb, disp, h, w);
1129
    break;
1130
 
1131
  case FS4_DITHER:
1132
    FS4DitherImage(l, Cr, Cb, disp, h, w);
1133
    break;
1134
 
1135
  case Twox2_DITHER:
1136
    Twox2DitherImage(l, Cr, Cb, disp, h, w);
1137
    break;
1138
 
1139
  case FULL_COLOR2_DITHER:
1140
    if (matched_depth >= 24)
1141
      Twox2Color32DitherImage(l, Cr, Cb, disp, h, w);
1142
    else
1143
      Twox2Color16DitherImage(l, Cr, Cb, disp, h, w);
1144
    break;
1145
  case FULL_COLOR_DITHER:
1146
    if (matched_depth >= 24)
1147
#endif
1148
 
1149
      Color32DitherImage(l, Cr, Cb, disp, h, w);
1150
 
1151
#ifndef DISABLE_DITHER
1152
    else
1153
      Color16DitherImage(l, Cr, Cb, disp, h, w);
1154
    break;
1155
 
1156
  case GRAY_DITHER:
1157
  case GRAY256_DITHER:
1158
    if (matched_depth == 8)
1159
      GrayDitherImage(l, Cr, Cb, disp, h, w);
1160
    else if (matched_depth == 16)
1161
      Gray16DitherImage(l, Cr, Cb, disp, h, w);
1162
    else if (matched_depth == 32 || matched_depth == 24)
1163
      Gray32DitherImage(l, Cr, Cb, disp, h, w);
1164
    break;
1165
 
1166
  case GRAY2_DITHER:
1167
  case GRAY2562_DITHER:
1168
    if (matched_depth == 8)
1169
      Gray2DitherImage(l, Cr, Cb, disp, h, w);
1170
    else if (matched_depth == 16)
1171
      Gray216DitherImage(l, Cr, Cb, disp, h, w);
1172
    else if (matched_depth == 32 || matched_depth == 24)
1173
      Gray232DitherImage(l, Cr, Cb, disp, h, w);
1174
    break;
1175
 
1176
  case NO_DITHER:
1177
    break;
1178
 
1179
  case PPM_DITHER:
1180
    Color32DitherImage(l, Cr, Cb, disp, h, w);
1181
    break;
1182
 
1183
  case ORDERED_DITHER:
1184
    OrderedDitherImage(l, Cr, Cb, disp, h, w);
1185
    break;
1186
 
1187
  case MONO_DITHER:
1188
    MonoDitherImage(l, Cr, Cb, disp, h, w);
1189
    break;
1190
 
1191
  case MONO_THRESHOLD:
1192
    MonoThresholdImage(l, Cr, Cb, disp, h, w);
1193
    break;
1194
 
1195
  case ORDERED2_DITHER:
1196
    Ordered2DitherImage(l, Cr, Cb, disp, h, w);
1197
    break;
1198
 
1199
  case MBORDERED_DITHER:
1200
    MBOrderedDitherImage(l, Cr, Cb, disp, h, w, vid_stream->ditherFlags);
1201
    break;
1202
  }
1203
#endif
1204
}