1 /* ScummVM - Graphic Adventure Engine
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #include "graphics/video/mpeg_player.h"
27 #include "common/file.h"
28 #include "common/system.h"
29 #include "common/util.h"
30 #include "graphics/scaler/intern.h"
34 BaseAnimationState::BaseAnimationState(OSystem
*sys
, int width
, int height
)
35 : _movieWidth(width
), _movieHeight(height
), _frameWidth(width
), _frameHeight(height
), _sys(sys
) {
37 const int screenW
= _sys
->getOverlayWidth();
38 const int screenH
= _sys
->getOverlayHeight();
40 _movieScale
= MIN(screenW
/ _movieWidth
, screenH
/ _movieHeight
);
42 assert(_movieScale
>= 1);
48 memset(&_overlayFormat
, 0, sizeof(_overlayFormat
));
52 BaseAnimationState::~BaseAnimationState() {
55 mpeg2_close(_mpegDecoder
);
67 bool BaseAnimationState::init(const char *name
) {
78 // Load lookup palettes
79 sprintf(tempFile
, "%s.pal", name
);
83 if (!f
.open(tempFile
)) {
84 warning("Cutscene: %s palette missing", tempFile
);
90 _palettes
[p
].end
= f
.readUint16LE();
91 _palettes
[p
].cnt
= f
.readUint16LE();
93 for (i
= 0; i
< _palettes
[p
].cnt
; i
++) {
94 _palettes
[p
].pal
[4 * i
] = f
.readByte();
95 _palettes
[p
].pal
[4 * i
+ 1] = f
.readByte();
96 _palettes
[p
].pal
[4 * i
+ 2] = f
.readByte();
97 _palettes
[p
].pal
[4 * i
+ 3] = 0;
99 for (; i
< 256; i
++) {
100 _palettes
[p
].pal
[4 * i
] = 0;
101 _palettes
[p
].pal
[4 * i
+ 1] = 0;
102 _palettes
[p
].pal
[4 * i
+ 2] = 0;
103 _palettes
[p
].pal
[4 * i
+ 3] = 0;
113 setPalette(_palettes
[_palNum
].pal
);
114 _lut
= _lut2
= _yuvLookup
[0];
117 buildLookup(_palNum
, 256);
118 _lut2
= _yuvLookup
[1];
119 _lutCalcNum
= (BITDEPTH
+ _palettes
[_palNum
].end
+ 2) / (_palettes
[_palNum
].end
+ 2);
122 _overlay
= (OverlayColor
*)calloc(_movieScale
* _movieWidth
* _movieScale
* _movieHeight
, sizeof(OverlayColor
));
127 _mpegFile
= new Common::File();
128 sprintf(tempFile
, "%s.mp2", name
);
129 if (!_mpegFile
->open(tempFile
)) {
130 warning("Cutscene: Could not open %s", tempFile
);
134 // Load and configure decoder
135 _mpegDecoder
= mpeg2_init();
136 if (_mpegDecoder
== NULL
) {
137 warning("Cutscene: Could not allocate an MPEG2 decoder");
141 _mpegInfo
= mpeg2_info(_mpegDecoder
);
145 #else /* USE_MPEG2 */
150 bool BaseAnimationState::decodeFrame() {
153 const mpeg2_sequence_t
*sequence_i
;
154 size_t size
= (size_t) -1;
155 static byte buf
[BUFFER_SIZE
];
158 state
= mpeg2_parse(_mpegDecoder
);
159 sequence_i
= _mpegInfo
->sequence
;
163 size
= _mpegFile
->read(buf
, BUFFER_SIZE
);
164 mpeg2_buffer(_mpegDecoder
, buf
, buf
+ size
);
169 if (_mpegInfo
->display_fbuf
) {
170 checkPaletteSwitch();
171 drawYUV(sequence_i
->width
, sequence_i
->height
, _mpegInfo
->display_fbuf
->buf
);
173 buildLookup(_palNum
+ 1, _lutCalcNum
);
189 bool BaseAnimationState::checkPaletteSwitch() {
191 // if we have reached the last image with this palette, switch to new one
192 if (_frameNum
== _palettes
[_palNum
].end
) {
193 unsigned char *l
= _lut2
;
195 setPalette(_palettes
[_palNum
].pal
);
196 _lutCalcNum
= (BITDEPTH
+ _palettes
[_palNum
].end
- (_frameNum
+ 1) + 2) / (_palettes
[_palNum
].end
- (_frameNum
+ 1) + 2);
206 void BaseAnimationState::handleScreenChanged() {
208 const int screenW
= _sys
->getOverlayWidth();
209 const int screenH
= _sys
->getOverlayHeight();
211 int newScale
= MIN(screenW
/ _movieWidth
, screenH
/ _movieHeight
);
213 assert(newScale
>= 1);
217 if (newScale
!= _movieScale
) {
218 // HACK: Since frames generally do not cover the entire screen,
219 // We need to undraw the old frame. This is a very hacky
220 // way of doing that.
221 OverlayColor
*buf
= (OverlayColor
*)calloc(screenW
* screenH
, sizeof(OverlayColor
));
222 _sys
->copyRectToOverlay(buf
, screenW
, 0, 0, screenW
, screenH
);
226 _movieScale
= newScale
;
227 _overlay
= (OverlayColor
*)calloc(_movieScale
* _movieWidth
* _movieScale
* _movieHeight
, sizeof(OverlayColor
));
237 * Build 'Best-Match' RGB lookup table
239 void BaseAnimationState::buildLookup(int p
, int lines
) {
255 for (ii
= 0; ii
< lines
; ii
++) {
256 r
= (-16 * 256 + (int) (256 * 1.596) * ((_cr
<< SHIFT
) - 128)) / 256;
257 for (cb
= 0; cb
<= BITDEPTH
; cb
++) {
258 g
= (-16 * 256 - (int) (0.813 * 256) * ((_cr
<< SHIFT
) - 128) - (int) (0.391 * 256) * ((cb
<< SHIFT
) - 128)) / 256;
259 b
= (-16 * 256 + (int) (2.018 * 256) * ((cb
<< SHIFT
) - 128)) / 256;
261 for (y
= 0; y
<= BITDEPTH
; y
++) {
263 int dis
= 2 * SQR(r
- _palettes
[p
].pal
[0]) + 4 * SQR(g
- _palettes
[p
].pal
[1]) + SQR(b
- _palettes
[p
].pal
[2]);
265 for (idx
= 1; idx
< 256; idx
++) {
266 long d2
= 2 * SQR(r
- _palettes
[p
].pal
[4 * idx
]) + 4 * SQR(g
- _palettes
[p
].pal
[4 * idx
+ 1]) + SQR(b
- _palettes
[p
].pal
[4 * idx
+ 2]);
278 r
-= (BITDEPTH
+ 1) * (1 << SHIFT
);
288 // The YUV to RGB conversion code is derived from SDL's YUV overlay code, which
289 // in turn appears to be derived from mpeg_play. The following copyright
290 // notices have been included in accordance with the original license. Please
291 // note that the term "software" in this context only applies to the two
292 // functions buildLookup() and plotYUV() below.
294 // Copyright (c) 1995 The Regents of the University of California.
295 // All rights reserved.
297 // Permission to use, copy, modify, and distribute this software and its
298 // documentation for any purpose, without fee, and without written agreement is
299 // hereby granted, provided that the above copyright notice and the following
300 // two paragraphs appear in all copies of this software.
302 // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
303 // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
304 // OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
305 // CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
307 // THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
308 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
309 // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
310 // ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
311 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
313 // Copyright (c) 1995 Erik Corry
314 // All rights reserved.
316 // Permission to use, copy, modify, and distribute this software and its
317 // documentation for any purpose, without fee, and without written agreement is
318 // hereby granted, provided that the above copyright notice and the following
319 // two paragraphs appear in all copies of this software.
321 // IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
322 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
323 // THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
324 // OF THE POSSIBILITY OF SUCH DAMAGE.
326 // ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
327 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
328 // PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
329 // BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
330 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
332 // Portions of this software Copyright (c) 1995 Brown University.
333 // All rights reserved.
335 // Permission to use, copy, modify, and distribute this software and its
336 // documentation for any purpose, without fee, and without written agreement
337 // is hereby granted, provided that the above copyright notice and the
338 // following two paragraphs appear in all copies of this software.
340 // IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
341 // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
342 // OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
343 // UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
345 // BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
346 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
347 // PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
348 // BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
349 // SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
351 void BaseAnimationState::buildLookup() {
352 // Do we already have lookup tables for this bit format?
353 Graphics::PixelFormat format
= _sys
->getOverlayFormat();
354 if (format
== _overlayFormat
&& _colorTab
&& _rgbToPix
)
360 _colorTab
= (int16
*)malloc(4 * 256 * sizeof(int16
));
362 int16
*Cr_r_tab
= &_colorTab
[0 * 256];
363 int16
*Cr_g_tab
= &_colorTab
[1 * 256];
364 int16
*Cb_g_tab
= &_colorTab
[2 * 256];
365 int16
*Cb_b_tab
= &_colorTab
[3 * 256];
367 _rgbToPix
= (OverlayColor
*)malloc(3 * 768 * sizeof(OverlayColor
));
369 OverlayColor
*r_2_pix_alloc
= &_rgbToPix
[0 * 768];
370 OverlayColor
*g_2_pix_alloc
= &_rgbToPix
[1 * 768];
371 OverlayColor
*b_2_pix_alloc
= &_rgbToPix
[2 * 768];
376 // Generate the tables for the display surface
378 for (i
= 0; i
< 256; i
++) {
379 // Gamma correction (luminescence table) and chroma correction
380 // would be done here. See the Berkeley mpeg_play sources.
383 Cr_r_tab
[i
] = (int16
) ( (0.419 / 0.299) * CR
) + 0 * 768 + 256;
384 Cr_g_tab
[i
] = (int16
) (-(0.299 / 0.419) * CR
) + 1 * 768 + 256;
385 Cb_g_tab
[i
] = (int16
) (-(0.114 / 0.331) * CB
);
386 Cb_b_tab
[i
] = (int16
) ( (0.587 / 0.331) * CB
) + 2 * 768 + 256;
389 // Set up entries 0-255 in rgb-to-pixel value tables.
390 for (i
= 0; i
< 256; i
++) {
391 r_2_pix_alloc
[i
+ 256] = format
.RGBToColor(i
, 0, 0);
392 g_2_pix_alloc
[i
+ 256] = format
.RGBToColor(0, i
, 0);
393 b_2_pix_alloc
[i
+ 256] = format
.RGBToColor(0, 0, i
);
396 // Spread out the values we have to the rest of the array so that we do
397 // not need to check for overflow.
398 for (i
= 0; i
< 256; i
++) {
399 r_2_pix_alloc
[i
] = r_2_pix_alloc
[256];
400 r_2_pix_alloc
[i
+ 512] = r_2_pix_alloc
[511];
401 g_2_pix_alloc
[i
] = g_2_pix_alloc
[256];
402 g_2_pix_alloc
[i
+ 512] = g_2_pix_alloc
[511];
403 b_2_pix_alloc
[i
] = b_2_pix_alloc
[256];
404 b_2_pix_alloc
[i
+ 512] = b_2_pix_alloc
[511];
407 _overlayFormat
= format
;
410 void BaseAnimationState::plotYUV(int width
, int height
, byte
*const *dat
) {
411 switch (_movieScale
) {
413 plotYUV1x(width
, height
, dat
);
416 plotYUV2x(width
, height
, dat
);
419 plotYUV3x(width
, height
, dat
);
424 void BaseAnimationState::plotYUV1x(int width
, int height
, byte
*const *dat
) {
429 byte
*lum2
= lum
+ width
;
435 OverlayColor
*row1
= _overlay
;
436 OverlayColor
*row2
= row1
+ _movieWidth
;
440 for (; height
> 0; height
-= 2) {
441 OverlayColor
*r1
= row1
;
442 OverlayColor
*r2
= row2
;
444 for (x
= width
; x
> 0; x
-= 2) {
445 register OverlayColor
*L
;
447 cr_r
= _colorTab
[*cr
+ 0 * 256];
448 crb_g
= _colorTab
[*cr
+ 1 * 256] + _colorTab
[*cb
+ 2 * 256];
449 cb_b
= _colorTab
[*cb
+ 3 * 256];
453 L
= &_rgbToPix
[*lum
++];
454 *r1
++ = L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
456 L
= &_rgbToPix
[*lum
++];
457 *r1
++ = L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
459 // Now, do second row.
461 L
= &_rgbToPix
[*lum2
++];
462 *r2
++ = L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
464 L
= &_rgbToPix
[*lum2
++];
465 *r2
++ = L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
470 row1
+= 2 * _movieWidth
;
471 row2
+= 2 * _movieWidth
;
475 void BaseAnimationState::plotYUV2x(int width
, int height
, byte
*const *dat
) {
480 byte
*lum2
= lum
+ width
;
486 OverlayColor
*row1
= _overlay
;
487 OverlayColor
*row2
= row1
+ 2 * 2 * _movieWidth
;
491 for (; height
> 0; height
-= 2) {
492 OverlayColor
*r1
= row1
;
493 OverlayColor
*r2
= row2
;
495 for (x
= width
; x
> 0; x
-= 2) {
496 register OverlayColor
*L
;
497 register OverlayColor C
;
499 cr_r
= _colorTab
[*cr
+ 0 * 256];
500 crb_g
= _colorTab
[*cr
+ 1 * 256] + _colorTab
[*cb
+ 2 * 256];
501 cb_b
= _colorTab
[*cb
+ 3 * 256];
505 L
= &_rgbToPix
[*lum
++];
506 C
= L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
510 L
= &_rgbToPix
[*lum
++];
511 C
= L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
515 // Now, do second row.
517 L
= &_rgbToPix
[*lum2
++];
518 C
= L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
522 L
= &_rgbToPix
[*lum2
++];
523 C
= L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
528 memcpy(row1
+ 2 * _movieWidth
, row1
, 2 * _movieWidth
* sizeof(OverlayColor
));
529 memcpy(row2
+ 2 * _movieWidth
, row2
, 2 * _movieWidth
* sizeof(OverlayColor
));
533 row1
+= 4 * 2 * _movieWidth
;
534 row2
+= 4 * 2 * _movieWidth
;
538 void BaseAnimationState::plotYUV3x(int width
, int height
, byte
*const *dat
) {
543 byte
*lum2
= lum
+ width
;
549 OverlayColor
*row1
= _overlay
;
550 OverlayColor
*row2
= row1
+ 3 * 3 * _movieWidth
;
554 for (; height
> 0; height
-= 2) {
555 OverlayColor
*r1
= row1
;
556 OverlayColor
*r2
= row2
;
558 for (x
= width
; x
> 0; x
-= 2) {
559 register OverlayColor
*L
;
560 register OverlayColor C
;
562 cr_r
= _colorTab
[*cr
+ 0 * 256];
563 crb_g
= _colorTab
[*cr
+ 1 * 256] + _colorTab
[*cb
+ 2 * 256];
564 cb_b
= _colorTab
[*cb
+ 3 * 256];
568 L
= &_rgbToPix
[*lum
++];
569 C
= L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
574 L
= &_rgbToPix
[*lum
++];
575 C
= L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
580 // Now, do second row.
582 L
= &_rgbToPix
[*lum2
++];
583 C
= L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
588 L
= &_rgbToPix
[*lum2
++];
589 C
= L
[cr_r
] | L
[crb_g
] | L
[cb_b
];
595 memcpy(row1
+ 3 * _movieWidth
, row1
, 3 * _movieWidth
* sizeof(OverlayColor
));
596 memcpy(row1
+ 2 * 3 * _movieWidth
, row1
, 3 * _movieWidth
* sizeof(OverlayColor
));
597 memcpy(row2
+ 3 * _movieWidth
, row2
, 3 * _movieWidth
* sizeof(OverlayColor
));
598 memcpy(row2
+ 2 * 3 * _movieWidth
, row2
, 3 * _movieWidth
* sizeof(OverlayColor
));
602 row1
+= 6 * 3 * _movieWidth
;
603 row2
+= 6 * 3 * _movieWidth
;
609 void BaseAnimationState::updateScreen() {
611 int width
= _movieScale
* _frameWidth
;
612 int height
= _movieScale
* _frameHeight
;
613 int pitch
= _movieScale
* _movieWidth
;
615 const int screenW
= _sys
->getOverlayWidth();
616 const int screenH
= _sys
->getOverlayHeight();
618 int x
= (screenW
- _movieScale
* _frameWidth
) / 2;
619 int y
= (screenH
- _movieScale
* _frameHeight
) / 2;
621 _sys
->copyRectToOverlay(_overlay
, pitch
, x
, y
, width
, height
);
623 _sys
->updateScreen();
626 } // End of namespace Graphics