Subversion Repositories shark

Rev

Rev 2 | Details | Compare with Previous | 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
/* ----------------------------- MNI Header -----------------------------------
46
@NAME       : wrapper.c
47
@INPUT      :
48
@OUTPUT     :
49
@RETURNS    :
50
@DESCRIPTION: Functions and variables used in the interface between
51
              user applications and the Berkely MPEG decoder.  This
52
              file essentially comprises the MNI front end to the
53
              Berkeley decoder; applications should NOT have access to any of
54
              these.  The functions in this file are the only ones to
55
              which users of the MPEG library have access; all other
56
              functions in the library are private.
57
@METHOD     :
58
@GLOBALS    :
59
@CALLS      :
60
@CREATED    :
61
@MODIFIED   :
62
---------------------------------------------------------------------------- */
63
 
64
#include <stdio.h>
65
#include <errno.h>
66
#include "video.h"
67
#include "proto.h"
68
#include "util.h"
69
#include "dither.h"
70
#include "mpeg.h"
71
 
72
#define BUF_LENGTH 100000
73
 
74
 
75
/*
76
 * Global variables shared between this file and the core MPEG decoder
77
 * (but nowhere else!)  - these are the only globals!
78
 */
79
int quietFlag=1, loopFlag=1,qualityFlag=0, requireKeypressFlag=0;
80
int framerate=0,gammaCorrectFlag=0, chromaCorrectFlag=0, noDisplayFlag=0;
81
int partialFlag=0,startFrame=-1, endFrame=-1;
82
double gammaCorrect = 1.0, chromaCorrect=1.0;
83
 
84
static int numMovies=0;
85
 
86
/* Prototypes for functions local to this file: */
87
 
88
void GetMPEGInfo (ImageDesc *Info);
89
 
90
int dprintf (char *format, ...) {}
91
 
92
 
93
/* ----------------------------- MNI Header -----------------------------------
94
@NAME       : OpenMPEG
95
@INPUT      : MPEGfile - pointer to a stream opened for reading, positioned
96
                         at the beginning of an MPEG stream
97
              ImgInfo  - pointer to an ImageDesc structure which will have
98
                         information such as frame height, width, depth
99
                         and size (total bytes per frame) put in it.
100
@OUTPUT     :
101
@RETURNS    :
102
@DESCRIPTION: Creates and initializes the variables needed to start
103
              reading/decoding an MPEG stream.  
104
 
105
              This function is part of the MNI front end to the Berkeley
106
              MPEG decoder, adapted from the original Berkeley code.
107
@METHOD     :
108
@GLOBALS    : LUM_RANGE, CR_RANGE, CB_RANGE
109
              lum_values, cr_values, cb_values
110
@CALLS      : GetMPEGInfo()
111
              init_tables()
112
              InitDither()
113
@CREATED    : 94/6/16, Greg Ward (adapted from main() in the original
114
              Berkeley source)
115
@MODIFIED   :
116
---------------------------------------------------------------------------- */
117
Boolean OpenMPEG (FILE *MPEGfile, ImageDesc *ImgInfo)
118
{
119
   VidStream *vid_stream;
120
   /*
121
    * First reinitialize these globals in case we're opening a second
122
    * (or more) file - thanks to Loren Holding (art054@cs.brown.edu)
123
    * for the patch
124
    */
125
 
126
    /* unneeded - done in NewVidStream or ResetVidStream */
127
 
128
   /*
129
    * Create the video stream and read the first chunk to get movie
130
    * stats -- width and height in particular.
131
    */
132
 
133
   if (ImgInfo->vid_stream==NULL) {    
134
     ImgInfo->vid_stream = vid_stream =NewVidStream((unsigned int) BUF_LENGTH);
135
   } else {
136
     vid_stream=ImgInfo->vid_stream;
137
     clear_data_stream(vid_stream);
138
     ResetVidStream(vid_stream);
139
   }
140
   vid_stream->input = MPEGfile;
141
   vid_stream->filename = "mniwrapper";
142
   vid_stream->matched_depth=24;
143
   vid_stream->ditherType=FULL_COLOR_DITHER; /* default */
144
 
145
   numMovies++;
146
 
147
   if (numMovies==1) {
148
       /* Allocate/initialize tables used for dithering (?) */
149
       lum_values = (int *) malloc(LUM_RANGE*sizeof(int));
150
       cr_values = (int *) malloc(CR_RANGE*sizeof(int));
151
       cb_values = (int *) malloc(CB_RANGE*sizeof(int));
152
 
153
      init_tables();            /* initialize decoding stuff */
154
      InitCrop();
155
 
156
#if 0
157
      InitDither(ImgInfo);      /* initializes dithering structures and */
158
                                /* colormap (i.e. this is where we do */
159
                                /* all dither-specific stuff) */
160
#endif
161
   }
162
 
163
   if (mpegVidRsrc(0, ImgInfo->vid_stream, 1, NULL )==NULL) {
164
      return FALSE;
165
   } else {
166
     GetMPEGInfo(ImgInfo);
167
     return TRUE;
168
   }
169
}     /* OpenMPEG () */
170
 
171
 
172
/* ----------------------------- MNI Header -----------------------------------
173
@NAME       : CloseMPEG
174
@INPUT      : (none)
175
@OUTPUT     : (none)
176
@RETURNS    : (void)
177
@DESCRIPTION: Frees up some of the memory allocated by OpenMPEG() (some
178
              is not freed because the Berkeley code doesn't take into
179
              account the fact that somebody might want to, say, free
180
              up the memory it allocates... someday, I'll probably have
181
              to hack into it to fix that, but not today thanks.)
182
@METHOD     :
183
@GLOBALS    : lum_values
184
              cr_values
185
              cb_values
186
@CALLS      : DestroyVidStream
187
@CREATED    : 94/6/27, Greg Ward
188
@MODIFIED   :
189
---------------------------------------------------------------------------- */
190
void CloseMPEG (ImageDesc *ImgInfo)
191
{
192
   DestroyVidStream(ImgInfo->vid_stream, NULL);
193
   free (lum_values);
194
   free (cr_values);
195
   free (cb_values);
196
}
197
 
198
 
199
 
200
/* ----------------------------- MNI Header -----------------------------------
201
@NAME       : RewindMPEG
202
@INPUT      : MPEGfile - the input stream where the MPEG's coming from
203
              Image    - image descriptor (just passed to OpenMPEG ())
204
@OUTPUT     : (none)
205
@RETURNS    : (void)
206
@DESCRIPTION: Resets things so that the caller can start reading the MPEG
207
              stream from the start again.   Note that the caller does NOT
208
              need to call OpenMPEG() again -- after a call to RewindMPEG(),
209
              the next call to GetMPEGFrame() will return the first frame
210
              of the MPEG.
211
@METHOD     :
212
@GLOBALS    :
213
@CALLS      :
214
@CREATED    : 94/7/20, Greg Ward
215
@MODIFIED   :
216
@COMMENTS   :
217
---------------------------------------------------------------------------- */
218
void RewindMPEG (FILE *MPEGfile, ImageDesc *Image)
219
{
220
   rewind (MPEGfile);
221
 
222
   OpenMPEG (MPEGfile, Image);
223
}
224
 
225
 
226
 
227
/* ----------------------------- MNI Header -----------------------------------
228
@NAME       : GetMPEGInfo
229
@INPUT      : vid_stream - a video stream that is open and has had at
230
                           least one call to mpegVidRsrc() performed on it
231
              Info       - a pointer to an ImageDesc struct in the caller's
232
                           space (i.e., the argument to OpenMPEG()) where
233
                           the image information will be copied
234
@OUTPUT     :
235
@RETURNS    : (void)
236
@DESCRIPTION: From the video stream, determines the width, height, pixel
237
              size and depth (in bits) and total image size (in bytes)
238
              for an MPEG stream.  Sets the fields in the structure
239
              pointed to by the Info pointer.
240
@METHOD     :
241
@GLOBALS    :
242
@CALLS      :
243
@CREATED    : 94/6/17, Greg Ward: based on code from ExecuteDisplay() in the
244
              original Berkeley source
245
@MODIFIED   :
246
---------------------------------------------------------------------------- */
247
void GetMPEGInfo (ImageDesc *Info)
248
{
249
#ifndef DISABLE_DITHER
250
   switch (Info->vid_stream->ditherType)
251
   {
252
      case Twox2_DITHER:
253
      {
254
         Info->Height = Info->vid_stream->mb_height * 32;
255
         Info->Width = Info->vid_stream->mb_width * 32;
256
         Info->Depth = 8;
257
         Info->PixelSize = 8;
258
         Info->BitmapPad = 8;
259
         break;
260
      }
261
      case FULL_COLOR_DITHER:
262
      {
263
#endif
264
         Info->Height = Info->vid_stream->mb_height * 16;
265
         Info->Width = Info->vid_stream->mb_width * 16;
266
         Info->Depth = 24;
267
         Info->PixelSize = 32;
268
         Info->BitmapPad = 32;
269
#ifndef DISABLE_DITHER
270
         break;
271
      }
272
 
273
      // MG
274
      case HALF_COLOR_DITHER:
275
         Info->Height = Info->vid_stream->mb_height * 16;
276
         Info->Width = Info->vid_stream->mb_width * 16;
277
         Info->Depth = 16;
278
         Info->PixelSize = 16;
279
         Info->BitmapPad = 16;
280
         break;
281
 
282
      case MONO_DITHER:
283
      case MONO_THRESHOLD:
284
      {
285
         Info->Height = Info->vid_stream->mb_height * 16;
286
         Info->Width = Info->vid_stream->mb_width * 16;
287
         Info->Depth = 1;
288
         Info->PixelSize = 1;
289
         Info->BitmapPad = 8;
290
         break;
291
      }
292
      default:                  /* including GRAY_DITHER and ORDERED_DITHER */
293
      {
294
         Info->Height = Info->vid_stream->mb_height * 16;
295
         Info->Width = Info->vid_stream->mb_width * 16;
296
         Info->Depth = 8;
297
         Info->PixelSize = 8;
298
         Info->BitmapPad = 8;
299
         break;
300
      }
301
   }     /* switch on ditherType */
302
#endif
303
 
304
   Info->Size = (Info->Height*Info->Width*Info->PixelSize) / 8;
305
   Info->PictureRate = Info->vid_stream->picture_rate;
306
   Info->BitRate = Info->vid_stream->bit_rate;
307
 
308
}     /* GetMPEGInfo () */
309
 
310
 
311
 
312
/* ----------------------------- MNI Header -----------------------------------
313
@NAME       : SetMPEGOption
314
@INPUT      : Option - which option to set
315
              Value  - what to set it to
316
@OUTPUT     :
317
@RETURNS    :
318
@DESCRIPTION: Set an MPEG option.  The options are all assigned intelligent
319
              defaults when they are created (as global variables), so
320
              calling SetMPEGOption is optional (as you might expect
321
              from the name).  Whether SetMPEGOption() is called before
322
              or after OpenMPEG() is important, but it depends on which
323
              option you're setting.  In particular, the dithering type
324
              and luminance/chromaticity ranges must be set before
325
              OpenMPEG(); but (unless your code is more clever than it
326
              needs to be), the colourmap indeces probably won't be set
327
              until after OpenMPEG().  RTFM for explanations of what the
328
              individual options do.
329
 
330
              The currently available options are:
331
                 MPEG_DITHER
332
                 MPEG_LUM_RANGE
333
                 MPEG_CR_RANGE
334
                 MPEG_CB_RANGE
335
                 MPEG_CMAP_INDEX
336
 
337
@METHOD     :
338
@GLOBALS    : Depending on the value of Option, sets one of the MPEG
339
              decoders global variables:
340
                 LUM_RANGE
341
                 CR_RANGE
342
                 CB_RANGE
343
@CALLS      :
344
@CREATED    : 94/6/17, Greg Ward.
345
@MODIFIED   : 95/3/18, GW: added MPEG_CMAP_INDEX option.
346
---------------------------------------------------------------------------- */
347
void SetMPEGOption (ImageDesc *Info, MPEGOptionEnum Option, int Value)
348
{
349
 
350
   switch (Option)
351
   {
352
      case MPEG_DITHER:    
353
#ifndef DISABLE_DITHER
354
         Info->vid_stream->ditherType = (DitherEnum) Value;
355
 
356
         InitDither(Info);      /* initializes dithering structures and */
357
                                /* colormap (i.e. this is where we do */
358
                                /* all dither-specific stuff) */
359
#endif
360
         break;
361
      case MPEG_LUM_RANGE: LUM_RANGE = Value; break;
362
      case MPEG_CR_RANGE:  CR_RANGE = Value; break;
363
      case MPEG_CB_RANGE:  CB_RANGE = Value; break;
364
#ifndef DISABLE_DITHER
365
      case MPEG_CMAP_INDEX:
366
      {
367
         int            i;
368
         unsigned char *cmap_index;
369
 
370
         cmap_index = (unsigned char *) Value;
371
         for (i = 0; i < Info->ColormapSize; i++)
372
         {
373
            pixel[i] = cmap_index[i];
374
         }
375
         break;
376
      }
377
#endif
378
 
379
   }
380
}     /* SetMPEGOption () */
381
 
382
 
383
 
384
/* ----------------------------- MNI Header -----------------------------------
385
@NAME       : GetMPEGFrame
386
@INPUT      :
387
@OUTPUT     : Frame - the image data, converted to RGB space, is
388
              copied to the area pointed to by Frame.  There must be
389
              enough room for the entire image; the ImageDesc
390
              structure returned by OpenMPEG() will tell you just how
391
              much memory this is.  The format of the data depends on
392
              the dithering type; for full colour dithering, there are
393
              four bytes per pixel: red, green, blue, and unused.
394
              (Perfect for passing to lrectwrite() or XPutImage().)
395
@RETURNS    : TRUE if there are still frames left to decode
396
              FALSE if we have just decoded the last frame
397
@DESCRIPTION: Part of the MNI front end to the Berkeley MPEG decoder.  
398
              Essentially reads, decodes, and converts to RGB space the
399
              next frame in the MPEG stream opened with OpenMPEG().
400
@METHOD     :
401
@GLOBALS    :
402
@CALLS      : mpegVidRsrc ()
403
@CREATED    : 94/6/16, Greg Ward
404
@MODIFIED   :
405
---------------------------------------------------------------------------- */
406
Boolean GetMPEGFrame (ImageDesc *image, char *Frame)
407
{
408
   Boolean   MovieDone = FALSE;
409
   int frames;
410
   char *CurrentImage;
411
 
412
   dprintf ("GetMPEGFrame: starting or continuing movie\n");
413
 
414
   frames=image->vid_stream->totNumFrames;
415
   while (!MovieDone && (frames==image->vid_stream->totNumFrames))
416
   {
417
      mpegVidRsrc(0,image->vid_stream,0, NULL);
418
      MovieDone = image->vid_stream->film_has_ended;
419
   }
420
 
421
   CurrentImage=(char *) image->vid_stream->current->display;
422
 
423
   dprintf ("\nGetMPEGFrame: just received a finished frame: "
424
            "copying from %08X to %08X\n", CurrentImage, Frame);
425
 
426
   memcpy (Frame, CurrentImage, image->Size);
427
   return (!MovieDone);
428
 
429
}     /* GetMPEGFrame () */
430
 
431
#ifndef DISABLE_DITHER
432
/* ----------------------------- MNI Header -----------------------------------
433
@NAME       : DoDitherImage
434
@INPUT      : l, Cr, Cb - pointers to the luminance, Cr, and Cb planes
435
              disp - ?
436
              h, w - height and width of image (?)
437
@OUTPUT     :
438
@RETURNS    :
439
@DESCRIPTION: Called when image needs to be dithered. Selects correct
440
              dither routine based on info in ditherType.
441
@METHOD     :
442
@GLOBALS    : ditherType
443
@CALLS      : One of the following, depending on the value of ditherType:
444
                 HybridDitherImage       (hybrid.c)
445
                 HybridErrorDitherImage  (hybriderr.c)
446
                 FS2FastDitherImage      (fs2fast.c)
447
                 FS2DitherImage          (fs2.c)
448
                 FS4DitherImage          (fs4.c)
449
                 Twox2DitherImage        (2x2.c)
450
                 ColorDitherImage        (16bit.c)
451
                 GrayDitherImage         (gray.c)
452
                 OrderedDitherImage      (ordered.c)
453
                 MonoDitherImage         (mono.c)
454
                 MonoThresholdImage      (mono.c)
455
                 Ordered2DitherImage     (ordered2.c)
456
                 MBOrderedDitherImage    (mb_ordered.c)
457
@CREATED    : (taken from the original Berkeley code)
458
@MODIFIED   :
459
---------------------------------------------------------------------------- */
460
void
461
DoDitherImage(vid_stream)
462
VidStream *vid_stream;
463
{
464
 unsigned char *l=vid_stream->current->luminance,
465
               *Cr=vid_stream->current->Cr,
466
               *Cb=vid_stream->current->Cb,
467
               *disp=vid_stream->current->display;
468
 int h=(int) vid_stream->mb_height * 16;
469
 int w=(int) vid_stream->mb_width * 16;
470
 int ditherType=vid_stream->ditherType;
471
 int matched_depth=vid_stream->matched_depth;
472
 
473
  switch(ditherType) {
474
  case HYBRID_DITHER:
475
    HybridDitherImage(l, Cr, Cb, disp, h, w);
476
    break;
477
 
478
  case HYBRID2_DITHER:
479
    HybridErrorDitherImage(l, Cr, Cb, disp, h, w);
480
    break;
481
 
482
  case FS2FAST_DITHER:
483
    FS2FastDitherImage(l, Cr, Cb, disp, h, w);
484
    break;
485
 
486
  case FS2_DITHER:
487
    FS2DitherImage(l, Cr, Cb, disp, h, w);
488
    break;
489
 
490
  case FS4_DITHER:
491
    FS4DitherImage(l, Cr, Cb, disp, h, w);
492
    break;
493
 
494
  case Twox2_DITHER:
495
    Twox2DitherImage(l, Cr, Cb, disp, h, w);
496
    break;
497
 
498
  case FULL_COLOR_DITHER:
499
    Color32DitherImage(l, Cr, Cb, disp, h, w);
500
    break;
501
 
502
  // MG
503
  case HALF_COLOR_DITHER:
504
    Color16DitherImage(l, Cr, Cb, disp, h, w);
505
    break;
506
 
507
  case GRAY_DITHER:
508
    GrayDitherImage(l, Cr, Cb, disp, h, w);
509
    break;
510
 
511
  case NO_DITHER:
512
    break;
513
 
514
  case PPM_DITHER:
515
    Color32DitherImage(l, Cr, Cb, disp, h, w);
516
    break;
517
 
518
  case ORDERED_DITHER:
519
    OrderedDitherImage(l, Cr, Cb, disp, h, w);
520
    break;
521
 
522
  case MONO_DITHER:
523
    MonoDitherImage(l, Cr, Cb, disp, h, w);
524
    break;
525
 
526
  case MONO_THRESHOLD:
527
    MonoThresholdImage(l, Cr, Cb, disp, h, w);
528
    break;
529
 
530
  case ORDERED2_DITHER:
531
    Ordered2DitherImage(l, Cr, Cb, disp, h, w);
532
    break;
533
 
534
  case MBORDERED_DITHER:
535
    MBOrderedDitherImage(l, Cr, Cb, disp, h, w, vid_stream->ditherFlags);
536
    break;
537
  }
538
}   /* DoDitherImage () */
539
#else
540
void
541
DoDitherImage(vid_stream)
542
VidStream *vid_stream;
543
{
544
 unsigned char *l=vid_stream->current->luminance,
545
               *Cr=vid_stream->current->Cr,
546
               *Cb=vid_stream->current->Cb,
547
               *disp=vid_stream->current->display;
548
 int h=(int) vid_stream->mb_height * 16;
549
 int w=(int) vid_stream->mb_width * 16;
550
 
551
 Color32DitherImage(l,Cr,Cb,disp,h,w);
552
}
553
#endif