Subversion Repositories shark

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Copyright (c) 1994 by Gregory P. Ward.
3
 * All rights reserved.
4
 *
5
 * This file is part of the MNI front end of the Berkeley MPEG decoder.
6
 *
7
 * Permission to use, copy, modify, and distribute this software and its
8
 * documentation for any purpose, without fee, and without written agreement is
9
 * hereby granted, provided that the above copyright notice and the following
10
 * two paragraphs appear in all copies of this software.
11
 *
12
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
13
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
14
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE
15
 * UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
16
 * SUCH DAMAGE.
17
 *
18
 * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT
19
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER
21
 * IS ON AN "AS IS" BASIS, AND THE AUTHOR HAS NO OBLIGATION TO PROVIDE
22
 * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.  
23
 */
24
/*
25
 * Portions of this software Copyright (c) 1995 Brown University.
26
 * All rights reserved.
27
 *
28
 * Permission to use, copy, modify, and distribute this software and its
29
 * documentation for any purpose, without fee, and without written agreement
30
 * is hereby granted, provided that the above copyright notice and the
31
 * following two paragraphs appear in all copies of this software.
32
 *
33
 * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT,
34
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
35
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
36
 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
 *
38
 * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
39
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
40
 * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
41
 * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
42
 * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
43
 */
44
 
45
/*
46
 *
47
 * Original C version by Greg Ward <greg@pet.mni.mcgill.ca>,
48
 * reentrant C++ version by Loring Holden <lsh@cs.brown.edu>
49
 *
50
 * All functions that have an "MNI Header" are rewritten from the original
51
 * MNI C function
52
 *
53
 */
54
 
55
#include "ANIMmpeg.H"
56
 
57
// These are MPEG decoder globals but shouldn't be, really;
58
int quietFlag=1, loopFlag=1,qualityFlag=0, requireKeypressFlag=0;
59
int framerate=0,gammaCorrectFlag=0, chromaCorrectFlag=0, noDisplayFlag=0;
60
int partialFlag=0,startFrame=-1, endFrame=-1;
61
double gammaCorrect = 1.0, chromaCorrect=1.0;
62
 
63
int ANIMmpeg::numMovies=0;
64
 
65
//
66
//Constructor
67
//
68
//
69
ANIMmpeg::ANIMmpeg(const char * const inFileName)
70
  : vid_stream(NULL)
71
{
72
   newMovie(inFileName);
73
   init();
74
}
75
 
76
//
77
//Copy constructor
78
//
79
ANIMmpeg::ANIMmpeg(const ANIMmpeg& rhs)
80
  : ANIMbase(rhs),
81
    vid_stream(NULL)
82
{
83
   newMovie(rhs.fileName);
84
   init();
85
}
86
 
87
//
88
// Takes in read-only string that is the the name of the new movie,
89
// if NULL, then just deallocates memory
90
//
91
void
92
ANIMmpeg::newMovie(const char * const infile)
93
{
94
   int stringLength = infile==NULL ? 0 : strlen(infile);
95
#ifndef NOTHREADS
96
   Boolean tmpThreaded=MultiThreaded;
97
 
98
   //  In case we're decoding in another thread...
99
   if (MultiThreaded && mp_man->processor(threadNumber)->running) {
100
       mp_man->processor(threadNumber)->wait_for_done();
101
   }
102
#endif
103
 
104
   // Clean up after old movie
105
   if (fileName) {
106
      delete [] fileName;
107
   }
108
   if (filePtr) fclose(filePtr);
109
   if (vid_stream) {
110
      DestroyVidStream(vid_stream, NULL);
111
      vid_stream=NULL;
112
   }
113
   if (frameBuffer) {
114
      Buffer(FALSE);
115
   }
116
#ifndef NOTHREADS
117
   MultiThread(FALSE);
118
#endif
119
 
120
   if (stringLength) {
121
      fileName = new char[stringLength];
122
      strcpy(fileName, infile);
123
      filePtr = fopen(fileName,"r");
124
#ifndef NOTHREADS
125
      MultiThread(tmpThreaded);
126
#endif
127
   }
128
 
129
   /* Initialize movie information */
130
   Height=Width=BlockHeight=BlockWidth=Depth=PixelSize=Size=BitmapPad=0;
131
   PictureRate=BitRate=0;
132
}
133
 
134
//
135
//Initialization used by all constructors
136
//
137
//
138
void
139
ANIMmpeg::init() {
140
   thread_routine=RunDecode;
141
   numMovies++;
142
   if (numMovies==1) {
143
       /* Allocate/initialize tables used for dithering (?) */
144
       lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
145
       cr_values = (int *) malloc(CR_RANGE*sizeof(int));
146
       cb_values = (int *) malloc(CB_RANGE*sizeof(int));
147
       init_tables();           /* initialize decoding stuff */
148
       InitCrop();
149
       InitDither();            /* initializes dithering structures and */
150
                                /* colormap (i.e. this is where we do */
151
                                /* all dither-specific stuff) */
152
   }
153
}
154
 
155
/* ----------------------------- MNI Header -----------------------------------
156
@NAME       : OpenMPEG
157
@INPUT      : MPEGfile - pointer to a stream opened for reading, positioned
158
                         at the beginning of an MPEG stream
159
              ImgInfo  - pointer to an ImageDesc structure which will have
160
                         information such as frame height, width, depth
161
                         and size (total bytes per frame) put in it.
162
@OUTPUT     :
163
@RETURNS    :
164
@DESCRIPTION: Creates and initializes the variables needed to start
165
              reading/decoding an MPEG stream.  
166
 
167
              This function is part of the MNI front end to the Berkeley
168
              MPEG decoder, adapted from the original Berkeley code.
169
@METHOD     :
170
@GLOBALS    : LUM_RANGE, CR_RANGE, CB_RANGE
171
              lum_values, cr_values, cb_values
172
@CALLS      : GetMPEGInfo()
173
              init_tables()
174
              InitDither()
175
@CREATED    : 94/6/16, Greg Ward (adapted from main() in the original
176
              Berkeley source)
177
@MODIFIED   : 95/10, Loring Holden (made reentrant and ported to C++)
178
---------------------------------------------------------------------------- */
179
Boolean ANIMmpeg::open()
180
{
181
   Boolean okMovie;
182
   /*
183
    * Create the video stream and read the first chunk to get movie
184
    * stats -- width and height in particular.
185
    */
186
#ifndef NOTHREADS
187
   if (MultiThreaded && (mp_man->processor(threadNumber)->running)) {
188
#ifdef sol
189
       fprintf(stderr,"%s:  Decode running when open called\n",
190
           fileName);
191
#else
192
       fprintf(stderr,"%s: Decode running when open called\n",fileName);
193
#endif
194
       fflush(stderr);
195
       exit(2);
196
   }
197
#endif
198
 
199
   if (vid_stream==NULL) {
200
     vid_stream =NewVidStream((unsigned int) BUF_LENGTH);
201
     /* Initialize start time */
202
     vid_stream->realTimeStart = ReadSysClock();
203
   } else {
204
     // clear_data_stream(vid_stream) already called in mpegVidRsrc
205
     ResetVidStream(vid_stream);
206
     allBuffered=FALSE;
207
     // call buffer destructor
208
     if (frameBuffer) Buffer(FALSE);
209
   }
210
 
211
   vid_stream->input = filePtr;
212
   vid_stream->filename = (char *) fileName;
213
   vid_stream->ditherType=FULL_COLOR_DITHER; /* default */
214
   frames=0;
215
   InitStream();
216
 
217
   okMovie=(mpegVidRsrc(0, vid_stream, 1, NULL)!=NULL);
218
   if (okMovie) {
219
     GetInfo();
220
     moreFrames=TRUE;
221
   } else moreFrames=FALSE;
222
 
223
#ifndef NOTHREADS
224
   if (!allBuffered && MultiThreaded && okMovie) {
225
      // Should check that nothing is running, but assume rewind has been
226
      // called 
227
      mp_man->processor(threadNumber)->start_execute(RunDecode,this,NULL);
228
   }
229
#endif
230
   return okMovie;
231
 
232
}     /* OpenMPEG () */
233
 
234
 
235
// Destructor
236
/* ----------------------------- MNI Header -----------------------------------
237
@NAME       : CloseMPEG
238
@INPUT      : (none)
239
@OUTPUT     : (none)
240
@RETURNS    : (void)
241
@DESCRIPTION: Frees up some of the memory allocated by OpenMPEG() (some
242
              is not freed because the Berkeley code doesn't take into
243
              account the fact that somebody might want to, say, free
244
              up the memory it allocates... someday, I'll probably have
245
              to hack into it to fix that, but not today thanks.)
246
@METHOD     :
247
@GLOBALS    : lum_values
248
              cr_values
249
              cb_values
250
@CALLS      : DestroyVidStream
251
@CREATED    : 94/6/27, Greg Ward
252
@MODIFIED   : 95/10, Loring Holden (made reentrant and ported to C++)
253
---------------------------------------------------------------------------- */
254
ANIMmpeg::~ANIMmpeg()
255
{
256
   newMovie(NULL);  //Like we are playing a new movie, but no new
257
                    //allocation
258
   // These stay around for the life of the program
259
   // free (lum_values);
260
   // free (cr_values);
261
   // free (cb_values);
262
}
263
 
264
 
265
 
266
/* ----------------------------- MNI Header -----------------------------------
267
@NAME       : RewindMPEG
268
@INPUT      : MPEGfile - the input stream where the MPEG's coming from
269
              Image    - image descriptor (just passed to OpenMPEG ())
270
@OUTPUT     : (none)
271
@RETURNS    : (void)
272
@DESCRIPTION: Resets things so that the caller can start reading the MPEG
273
              stream from the start again.  Note that the caller does NOT
274
              need to call OpenMPEG() again -- after a call to RewindMPEG(),
275
              the next call to GetMPEGFrame() will return the first frame
276
              of the MPEG.
277
@METHOD     :
278
@GLOBALS    :
279
@CALLS      :
280
@CREATED    : 94/7/20, Greg Ward
281
@MODIFIED   : 95/10, Loring Holden (made reentrant and ported to C++)
282
@COMMENTS   :
283
---------------------------------------------------------------------------- */
284
void ANIMmpeg::rewind()
285
{
286
#ifndef NOTHREADS
287
   if (MultiThreaded && (mp_man->processor(threadNumber)->running)) {
288
#ifdef sol
289
       fprintf(stderr,"%s:  Decode running when rewind called\n",
290
           fileName);
291
#else
292
       fprintf(stderr,"%s: Decode running when rewind called\n",fileName);
293
#endif
294
       fflush(stderr);
295
       exit(2);
296
   }
297
#endif
298
 
299
   if (!allBuffered) {
300
     ::rewind(filePtr);
301
     open();
302
   } else {
303
     // do buffering stuff here
304
   }
305
}
306
 
307
 
308
 
309
/* ----------------------------- MNI Header -----------------------------------
310
@NAME       : GetMPEGInfo
311
@INPUT      : vid_stream - a video stream that is open and has had at
312
                           least one call to mpegVidRsrc() performed on it
313
              Info       - a pointer to an ImageDesc struct in the caller's
314
                           space (i.e., the argument to OpenMPEG()) where
315
                           the image information will be copied
316
@OUTPUT     :
317
@RETURNS    : (void)
318
@DESCRIPTION: From the video stream, determines the width, height, pixel
319
              size and depth (in bits) and total image size (in bytes)
320
              for an MPEG stream.  Sets the global variable Info
321
              (part of the interface between wrapper.c and globals.c),
322
              and then copies that struct to the user application's
323
              space via the Info pointer.
324
@METHOD     :
325
@GLOBALS    :
326
@CALLS      :
327
@CREATED    : 94/6/17, Greg Ward: based on code from ExecuteDisplay() in the
328
              original Berkeley source
329
@MODIFIED   : 95/10, Loring Holden (made reentrant and ported to C++)
330
---------------------------------------------------------------------------- */
331
void ANIMmpeg::GetInfo()
332
{
333
#ifndef DISABLE_DITHER
334
   switch (vid_stream->ditherType)
335
   {
336
      case Twox2_DITHER:
337
      {
338
         Height = vid_stream->v_size;
339
         Width = vid_stream->h_size;
340
         BlockHeight=vid_stream->mb_height;
341
         BlockWidth=vid_stream->mb_width;
342
         Depth = 8;
343
         PixelSize = 8;
344
         BitmapPad = 8;
345
         break;
346
      }
347
      case FULL_COLOR_DITHER:
348
      {
349
#endif
350
         Height = vid_stream->v_size;
351
         Width = vid_stream->h_size;
352
         BlockHeight=vid_stream->mb_height;
353
         BlockWidth=vid_stream->mb_width;
354
         Depth = 24;
355
         PixelSize = 32;
356
         BitmapPad = 32;
357
#ifndef DISABLE_DITHER
358
         break;
359
      }
360
      case MONO_DITHER:
361
      case MONO_THRESHOLD:
362
      {
363
         Height = vid_stream->v_size;
364
         Width = vid_stream->h_size;
365
         Depth = 1;
366
         PixelSize = 1;
367
         BitmapPad = 8;
368
         break;
369
      }
370
      default:                  /* including GRAY_DITHER and ORDERED_DITHER */
371
      {
372
         Height = vid_stream->v_size;
373
         Width = vid_stream->h_size;
374
         Depth = 8;
375
         PixelSize = 8;
376
         BitmapPad = 8;
377
         break;
378
      }
379
   }     /* switch on ditherType */
380
#endif
381
 
382
   Size = (BlockHeight*16*BlockWidth*16*PixelSize) / 8;
383
   PictureRate = vid_stream->picture_rate;
384
   BitRate = vid_stream->bit_rate;
385
 
386
}     /* GetMPEGInfo () */
387
 
388
/* ----------------------------- MNI Header -----------------------------------
389
@NAME       : GetMPEGFrame
390
@INPUT      :
391
@OUTPUT     : Frame - the image data, converted to RGB space, is
392
              copied to the area pointed to by Frame.  There must be
393
              enough room for the entire image; the ImageDesc
394
              structure returned by OpenMPEG() will tell you just how
395
              much memory this is.  The format of the data depends on
396
              the dithering type; for full colour dithering, there are
397
              four bytes per pixel: red, green, blue, and unused.
398
              (Perfect for passing to lrectwrite() or XPutImage().)
399
@RETURNS    : TRUE if there are still frames left to decode
400
              FALSE if we have just decoded the last frame
401
@DESCRIPTION: Part of the MNI front end to the Berkeley MPEG decoder.  
402
              Essentially reads, decodes, and converts to RGB space the
403
              next frame in the MPEG stream opened with OpenMPEG().
404
@METHOD     :
405
@GLOBALS    :
406
@CALLS      : mpegVidRsrc ()
407
@CREATED    : 94/6/16, Greg Ward
408
@MODIFIED   : 95/10, Loring Holden (made reentrant and ported to C++)
409
---------------------------------------------------------------------------- */
410
void *ANIMmpeg::RunDecode(void *ptr, void *)
411
{
412
   ANIMmpeg *movie=(ANIMmpeg *) ptr;
413
   Boolean   MovieDone = FALSE;
414
   int frames;
415
 
416
#if 0
417
   dprintf ("GetMPEGFrame: starting or continuing movie\n");
418
#endif
419
 
420
   frames=movie->vid_stream->totNumFrames;
421
   while (!MovieDone && (frames==movie->vid_stream->totNumFrames))
422
   {
423
      mpegVidRsrc(0,movie->vid_stream,0, NULL);
424
      MovieDone = movie->vid_stream->film_has_ended;
425
   }
426
 
427
   return NULL;
428
 
429
}     /* GetMPEGFrame () */
430
 
431
Boolean ANIMmpeg::GetFrame(char **Frame, Boolean *newFrame)
432
{
433
   void *CurrentImage;
434
   int looped;
435
 
436
   if ((vid_stream==NULL) && !open()) {
437
        *newFrame=FALSE;
438
        return FALSE;
439
   }
440
 
441
   if (!allBuffered) {
442
#ifndef NOTHREADS
443
      if (MultiThreaded) {
444
         mp_man->processor(threadNumber)->wait_for_done();
445
      } else {
446
         ANIMmpeg::RunDecode(this,NULL);
447
      }
448
#else
449
      ANIMmpeg::RunDecode(this,NULL);
450
#endif
451
      moreFrames=!vid_stream->film_has_ended;
452
      CurrentImage=(void *) vid_stream->current->display;
453
      if (buffering) {
454
         // copy CurrentImage to the right place in the array
455
         if (!frameBuffer->addToBuffer(CurrentImage)) {
456
            // ran out of memory - can't buffer
457
            Buffer(FALSE);
458
            fflush(stdout);
459
            fprintf(stderr,"%s: no more room to buffer\n",fileName);
460
            fflush(stderr);
461
         } else if (!moreFrames) {
462
            allBuffered=TRUE;
463
            moreFrames=TRUE;
464
         }
465
      }
466
#if 0
467
      dprintf ("\nGetMPEGFrame: just received a finished frame: ",
468
            "copying from %08X to %08X\n", CurrentImage, Frame);
469
#endif
470
      memcpy ((void *) *Frame, CurrentImage, Size);
471
 
472
      if (allBuffered) {
473
         int totFrames=vid_stream->totNumFrames;
474
 
475
         DestroyVidStream(vid_stream,NULL);
476
         // This is a hack in order to use PrintTimeInfo
477
         //   - Create a NewVidStream just to use realTimeStart
478
         //   - all the image information is deallocated, so we do save space
479
         vid_stream =NewVidStream((unsigned int) BUF_LENGTH);
480
         vid_stream->totNumFrames=totFrames;
481
         /* Initialize start time */
482
         vid_stream->realTimeStart = ReadSysClock();
483
      }
484
 
485
   }  else {
486
      // set moreFrames 
487
      moreFrames=TRUE;
488
      // set CurrentImage to point to the right place in the array
489
      *Frame=(char *) frameBuffer->nextBufferItem(&looped);
490
      if (looped) {
491
        PrintTimeInfo(vid_stream);
492
        vid_stream->realTimeStart = ReadSysClock();
493
      }
494
   }
495
 
496
#ifndef NOTHREADS
497
   if (!allBuffered && MultiThreaded && moreFrames) {
498
      mp_man->processor(threadNumber)->start_execute(RunDecode,this,NULL);
499
   }
500
#endif
501
 
502
   frames++;
503
   *newFrame=TRUE;
504
   return moreFrames;
505
}
506
 
507
#ifndef DISABLE_DITHER
508
/* ----------------------------- MNI Header -----------------------------------
509
@NAME       : DoDitherImage
510
@INPUT      : l, Cr, Cb - pointers to the luminance, Cr, and Cb planes
511
              disp - ?
512
              h, w - height and width of image (?)
513
@OUTPUT     :
514
@RETURNS    :
515
@DESCRIPTION: Called when image needs to be dithered. Selects correct
516
              dither routine based on info in ditherType.
517
@METHOD     :
518
@GLOBALS    : ditherType
519
@CALLS      : One of the following, depending on the value of ditherType:
520
                 HybridDitherImage       (hybrid.c)
521
                 HybridErrorDitherImage  (hybriderr.c)
522
                 FS2FastDitherImage      (fs2fast.c)
523
                 FS2DitherImage          (fs2.c)
524
                 FS4DitherImage          (fs4.c)
525
                 Twox2DitherImage        (2x2.c)
526
                 ColorDitherImage        (16bit.c)
527
                 GrayDitherImage         (gray.c)
528
                 OrderedDitherImage      (ordered.c)
529
                 MonoDitherImage         (mono.c)
530
                 MonoThresholdImage      (mono.c)
531
                 Ordered2DitherImage     (ordered2.c)
532
                 MBOrderedDitherImage    (mb_ordered.c)
533
@CREATED    : (taken from the original Berkeley code)
534
@MODIFIED   :
535
---------------------------------------------------------------------------- */
536
void
537
DoDitherImage(VidStream *vid_stream)
538
{
539
 unsigned char *l=vid_stream->current->luminance,
540
               *Cr=vid_stream->current->Cr,
541
               *Cb=vid_stream->current->Cb,
542
               *disp=vid_stream->current->display;
543
 int h=(int) vid_stream->mb_height * 16;
544
 int w=(int) vid_stream->mb_width * 16;
545
 int ditherType=vid_stream->ditherType;
546
 int matched_depth=vid_stream->matched_depth;
547
 
548
  switch(ditherType) {
549
  case HYBRID_DITHER:
550
    HybridDitherImage(l, Cr, Cb, disp, h, w);
551
    break;
552
 
553
  case HYBRID2_DITHER:
554
    HybridErrorDitherImage(l, Cr, Cb, disp, h, w);
555
    break;
556
 
557
  case FS2FAST_DITHER:
558
    FS2FastDitherImage(l, Cr, Cb, disp, h, w);
559
    break;
560
 
561
  case FS2_DITHER:
562
    FS2DitherImage(l, Cr, Cb, disp, h, w);
563
    break;
564
 
565
  case FS4_DITHER:
566
    FS4DitherImage(l, Cr, Cb, disp, h, w);
567
    break;
568
 
569
  case Twox2_DITHER:
570
    Twox2DitherImage(l, Cr, Cb, disp, h, w);
571
    break;
572
 
573
  case FULL_COLOR_DITHER:
574
    Color32DitherImage(l, Cr, Cb, disp, h, w);
575
    break;
576
 
577
  case GRAY_DITHER:
578
    GrayDitherImage(l, Cr, Cb, disp, h, w);
579
    break;
580
 
581
  case NO_DITHER:
582
    break;
583
 
584
  case PPM_DITHER:
585
    Color32DitherImage(l, Cr, Cb, disp, h, w);
586
    break;
587
 
588
  case ORDERED_DITHER:
589
    OrderedDitherImage(l, Cr, Cb, disp, h, w);
590
    break;
591
 
592
  case MONO_DITHER:
593
    MonoDitherImage(l, Cr, Cb, disp, h, w);
594
    break;
595
 
596
  case MONO_THRESHOLD:
597
    MonoThresholdImage(l, Cr, Cb, disp, h, w);
598
    break;
599
 
600
  case ORDERED2_DITHER:
601
    Ordered2DitherImage(l, Cr, Cb, disp, h, w);
602
    break;
603
 
604
  case MBORDERED_DITHER:
605
    MBOrderedDitherImage(l, Cr, Cb, disp, h, w, vid_stream->ditherFlags);
606
    break;
607
  }
608
}   /* DoDitherImage () */
609
#else
610
void
611
DoDitherImage(VidStream *vid_stream)
612
{
613
 unsigned char *l=vid_stream->current->luminance,
614
               *Cr=vid_stream->current->Cr,
615
               *Cb=vid_stream->current->Cb,
616
               *disp=vid_stream->current->display;
617
 int h=(int) vid_stream->mb_height * 16;
618
 int w=(int) vid_stream->mb_width * 16;
619
 
620
 Color32DitherImage(l,Cr,Cb,disp,h,w);
621
}
622
#endif
623
 
624
/* ----------------------------- MNI Header -----------------------------------
625
@NAME       : InitColormap
626
@INPUT      : (none)
627
@OUTPUT     : *NumColors - number of entries in the newly-created colormap
628
              *Map - an array of colourmap entries; each one contains a
629
                     red, green, and blue byte-values (0 .. 255).  
630
                     *Map[i] gives the colour to display a pixel value i.
631
@RETURNS    : (none)
632
@DESCRIPTION: Creates a colour map used for most dithering methods
633
              (everything except full-colour, gray, and monochrome).
634
              The colour map itself is pretty self-explanatory -- a
635
              pixel with value i is to be displayed using the red, green
636
              and blue values in *Map[i] after InitColormap() is done.
637
@METHOD     :
638
@GLOBALS    :
639
@CALLS      :
640
@CREATED    : 95/3/4, Greg Ward: based on InitColorDisplay(), from gdith.c
641
                                 in the original Berkeley player
642
@MODIFIED   :
643
---------------------------------------------------------------------------- */
644
#ifndef DISABLE_DITHER
645
static void
646
InitColormap (int *NumColors, ColormapEntry **Map)
647
{
648
   int i, lum_num, cr_num, cb_num;
649
 
650
   *NumColors =  LUM_RANGE*CB_RANGE*CR_RANGE;
651
   *Map = (ColormapEntry *) malloc (*NumColors * sizeof (ColormapEntry));
652
 
653
   for (i = 0; i < *NumColors; i++)
654
   {
655
      lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
656
      cr_num = (i / CB_RANGE)%CR_RANGE;
657
      cb_num = i % CB_RANGE;
658
 
659
/*      ConvertColor(lum_values[lum_num], cr_values[cr_num], cb_values[cb_num],
660
                   &(*Map)[i].red, &(*Map)[i].green, &(*Map)[i].blue);
661
*/
662
      pixel[i] = i;
663
   }
664
}
665
#endif
666
 
667
 
668
/* ----------------------------- MNI Header -----------------------------------
669
@NAME       : InitGrayColormap
670
@INPUT      : (none)
671
@OUTPUT     : *NumColors - number of entries in the newly-created colormap
672
              *Map - an array of colourmap entries
673
@RETURNS    : (none)
674
@DESCRIPTION: Creates a colour map used for gray-scale dithering, i.e.
675
              the red/green/blue values are the same for any given
676
              pixel value.
677
@METHOD     :
678
@GLOBALS    :
679
@CALLS      :
680
@CREATED    : 95/3/4, Greg Ward: based on InitGrayDisplay(), from gdith.c
681
                                 in the original Berkeley player
682
@MODIFIED   :
683
---------------------------------------------------------------------------- */
684
#ifndef DISABLE_DITHER
685
static void
686
InitGrayColormap (int *NumColors, ColormapEntry **Map)
687
{
688
   int  i;
689
 
690
   *NumColors =  NUM_COLORS;
691
   *Map = (ColormapEntry *) malloc (*NumColors * sizeof (ColormapEntry));
692
 
693
   for (i = 0; i < *NumColors; i++)
694
   {
695
      (*Map)[i].red = (*Map)[i].green = (*Map)[i].blue = i;
696
      pixel[i] = i;
697
   }
698
}
699
#endif
700
 
701
 
702
/* ----------------------------- MNI Header -----------------------------------
703
@NAME       : InitDither
704
@INPUT      : Image - pointer to the image descriptor for the current MPEG
705
@OUTPUT     : ColormapSize, Colormap - the colour map for
706
              this movie, as initialized by either InitColormap or
707
              InitGrayColormap (unless the current dithering scheme
708
              is full colour, in which case there is no colour map)
709
@RETURNS    : (none)
710
@DESCRIPTION: Does all initialization particular to the type of dithering
711
              being used.  Basically, sets up the internal data structures
712
              needed by the dithering code, and then sets up a colour map
713
              needed to display the pixels output by the ditherers.
714
@METHOD     :
715
@GLOBALS    :
716
@CALLS      : InitColor     (for most dithering methods)
717
              InitColormap  (for most dithering methods)
718
              InitGrayColormap (for gray-scale dithering)
719
              Init(..)Dither  (.. = the current dithering method)
720
@CREATED    : 95/3/3, Greg Ward: taken mostly from main() in the original
721
                                 Berkeley player
722
@MODIFIED   :
723
---------------------------------------------------------------------------- */
724
void
725
ANIMmpeg::InitDither(unsigned long red,
726
                      unsigned long green,
727
                      unsigned long blue)
728
{
729
   LUM_RANGE = 8;
730
   CR_RANGE = 4;
731
   CB_RANGE = 4;
732
#ifndef DISABLE_DITHER
733
   switch (vid_stream->ditherType)
734
   {
735
      case HYBRID_DITHER:
736
         InitColor ();
737
         InitHybridDither ();
738
         InitColormap (&ColormapSize, &Colormap);
739
         break;
740
 
741
      case HYBRID2_DITHER:
742
         InitColor ();
743
         InitHybridErrorDither ();
744
         InitColormap (&ColormapSize, &Colormap);
745
         break;
746
 
747
      case FS4_DITHER:
748
         InitColor ();
749
         InitFS4Dither ();
750
         InitColormap (&ColormapSize, &Colormap);
751
         break;
752
 
753
      case FS2_DITHER:
754
         InitColor ();
755
         InitFS2Dither ();
756
         InitColormap (&ColormapSize, &Colormap);
757
         break;
758
 
759
      case FS2FAST_DITHER:
760
         InitColor ();
761
         InitFS2FastDither ();
762
         InitColormap (&ColormapSize, &Colormap);
763
         break;
764
 
765
      case Twox2_DITHER:
766
         InitColor ();
767
         Init2x2Dither ();
768
         InitColormap (&ColormapSize, &Colormap);
769
         PostInit2x2Dither ();
770
         break;
771
 
772
      case GRAY_DITHER:
773
         InitGrayColormap (&ColormapSize, &Colormap);
774
         break;
775
      case FULL_COLOR_DITHER:
776
#endif
777
         wpixel[0]=red;
778
         wpixel[1]=green;
779
         wpixel[2]=blue;
780
         InitColorDither(1);
781
#ifndef DISABLE_DITHER
782
         break;
783
 
784
      case NO_DITHER:
785
         break;
786
 
787
      case ORDERED_DITHER:
788
         InitColor ();
789
         InitOrderedDither ();
790
         InitColormap (&ColormapSize, &Colormap);
791
         break;
792
 
793
      case MONO_DITHER:
794
      case MONO_THRESHOLD:
795
         break;
796
 
797
      case ORDERED2_DITHER:
798
         InitColor ();
799
         InitColormap (&ColormapSize, &Colormap);
800
         InitOrdered2Dither ();
801
         break;
802
 
803
      case MBORDERED_DITHER:
804
         InitColor ();
805
         InitColormap (&ColormapSize, &Colormap);
806
         InitMBOrderedDither ();
807
         break;
808
 
809
      case PPM_DITHER:
810
         ColormapSize = -1;
811
         Colormap = NULL;
812
         wpixel[0] = 0xff;
813
         wpixel[1] = 0xff00;
814
         wpixel[2] = 0xff0000;
815
         vid_stream->matched_depth=24;
816
         InitColorDither(TRUE);
817
         break;
818
   }
819
#endif
820
}  
821
 
822
//
823
//
824
//
825
void
826
ANIMmpeg::InitStream()
827
{
828
   if ((vid_stream->ditherType==FULL_COLOR_DITHER) ||
829
       (vid_stream->ditherType==PPM_DITHER)) {
830
         vid_stream->matched_depth=24;
831
//       InitColorDither(1);
832
   }
833
}