aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorbjörn Andersson2005-03-06 14:12:40 +0000
committerTorbjörn Andersson2005-03-06 14:12:40 +0000
commite3105f926b1da0ffa737abcaf1bd9817743df415 (patch)
tree6a45844b7440f40d82ec2c9788e9f5c6bcfa1a8e
parentb7c2926a0b29d4eed35ecc440270eb1f0c8eddc6 (diff)
downloadscummvm-rg350-e3105f926b1da0ffa737abcaf1bd9817743df415.tar.gz
scummvm-rg350-e3105f926b1da0ffa737abcaf1bd9817743df415.tar.bz2
scummvm-rg350-e3105f926b1da0ffa737abcaf1bd9817743df415.zip
Applied patch #1155731, reducing the memory usage of the MPEG player by
about 8 MB. svn-id: r17007
-rw-r--r--TODO6
-rw-r--r--graphics/animation.cpp231
-rw-r--r--graphics/animation.h10
-rw-r--r--sword1/animation.cpp4
-rw-r--r--sword2/driver/animation.cpp4
5 files changed, 183 insertions, 72 deletions
diff --git a/TODO b/TODO
index ec848b6c4b..f3e7b3e1c3 100644
--- a/TODO
+++ b/TODO
@@ -94,12 +94,6 @@ General
some kind of main loop, which, besides many other things, also polls and
dispatches events. The idea is to turn this around: the event loop
frequently gives the engine time to do these "other things".
-* Try to reduce the memory footprint of the MPEG player. Right now it allocates
- an 8 MB lookup table for YUV->RGB conversion. Perhaps we could borrow some
- code from SDL's software implementation of YUV overlays. (It might even be
- possible to expose some of SDL's YUV overlay API as an optional part of the
- backend, but I don't know enough about it to get it to work. We'd still need
- our own implementation as a fallback, though.)
* Make the autosave interval configurable (via GUI, command line, config file).
* Maybe add ways to modify the game configs via the command line. E.g. allow
./scummvm --add new_target --path=/foo monkey2
diff --git a/graphics/animation.cpp b/graphics/animation.cpp
index 8337af4a37..883baff8e3 100644
--- a/graphics/animation.cpp
+++ b/graphics/animation.cpp
@@ -26,11 +26,17 @@
#include "common/file.h"
#include "common/system.h"
#include "common/util.h"
+#include "common/scaler/intern.h"
namespace Graphics {
BaseAnimationState::BaseAnimationState(SoundMixer *snd, OSystem *sys, int width, int height)
: MOVIE_WIDTH(width), MOVIE_HEIGHT(height), _snd(snd), _sys(sys) {
+#ifndef BACKEND_8BIT
+ colortab = NULL;
+ rgb_2_pix = NULL;
+ bitFormat = 0;
+#endif
}
BaseAnimationState::~BaseAnimationState() {
@@ -42,6 +48,8 @@ BaseAnimationState::~BaseAnimationState() {
#ifndef BACKEND_8BIT
_sys->hideOverlay();
free(overlay);
+ free(colortab);
+ free(rgb_2_pix);
#endif
delete bgSoundStream;
#endif
@@ -297,87 +305,194 @@ void BaseAnimationState::buildLookup(int p, int lines) {
#else
-OverlayColor *BaseAnimationState::lookup = 0;
+// The YUV to RGB conversion code is derived from SDL's YUV overlay code, which
+// in turn appears to be derived from mpeg_play. The following copyright
+// notices have been included in accordance with the original license. Please
+// note that the term "software" in this context only applies to the two
+// functions buildLookup() and plotYUV() below.
+
+// Copyright (c) 1995 The Regents of the University of California.
+// All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation for any purpose, without fee, and without written agreement is
+// hereby granted, provided that the above copyright notice and the following
+// two paragraphs appear in all copies of this software.
+//
+// IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+// OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+// CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+// ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+// PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+// Copyright (c) 1995 Erik Corry
+// All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation for any purpose, without fee, and without written agreement is
+// hereby granted, provided that the above copyright notice and the following
+// two paragraphs appear in all copies of this software.
+//
+// IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+// THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+// BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
+// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+// Portions of this software Copyright (c) 1995 Brown University.
+// All rights reserved.
+//
+// Permission to use, copy, modify, and distribute this software and its
+// documentation for any purpose, without fee, and without written agreement
+// is hereby granted, provided that the above copyright notice and the
+// following two paragraphs appear in all copies of this software.
+//
+// IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
+// DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+// OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
+// UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+// PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+// BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
+// SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-/**
- * This function should be called when the screen changes to invalidate and,
- * optionally, rebuild the lookup table.
- * @param rebuild If true, rebuild the table.
- */
+void BaseAnimationState::buildLookup() {
+ // Do we already have lookup tables for this bit format?
+ if (gBitFormat == bitFormat && colortab && rgb_2_pix)
+ return;
-// FIXME: We will need to call the function from the game's main event loop
-// as well, not just the cutscene players' ones.
+ free(colortab);
+ free(rgb_2_pix);
-// FIXME: It would be nice with a heuristic to check if the table really does
-// need to be rebuilt.
+ colortab = (int16 *)malloc(4 * 256 * sizeof(int16));
-void BaseAnimationState::invalidateLookup(bool rebuild) {
- free(lookup);
- lookup = 0;
- if (rebuild)
- buildLookup();
-}
+ int16 *Cr_r_tab = &colortab[0 * 256];
+ int16 *Cr_g_tab = &colortab[1 * 256];
+ int16 *Cb_g_tab = &colortab[2 * 256];
+ int16 *Cb_b_tab = &colortab[3 * 256];
-void BaseAnimationState::buildLookup() {
- if (lookup)
- return;
+ rgb_2_pix = (uint16 *)malloc(3 * 768 * sizeof(uint16));
- lookup = (OverlayColor *)calloc((BITDEPTH+1) * (BITDEPTH+1) * 256, sizeof(OverlayColor));
- if (!lookup) {
- warning("Not enough memory to allocate LUT - cannot play sequence");
- return;
+ uint16 *r_2_pix_alloc = &rgb_2_pix[0 * 768];
+ uint16 *g_2_pix_alloc = &rgb_2_pix[1 * 768];
+ uint16 *b_2_pix_alloc = &rgb_2_pix[2 * 768];
+
+ int16 CR, CB;
+ int i;
+
+ // Generate the tables for the display surface
+
+ for (i = 0; i < 256; i++) {
+ // Gamma correction (luminescence table) and chroma correction
+ // would be done here. See the Berkeley mpeg_play sources.
+
+ CR = CB = (i - 128);
+ Cr_r_tab[i] = (int16) ( (0.419 / 0.299) * CR);
+ Cr_g_tab[i] = (int16) (-(0.299 / 0.419) * CR);
+ Cb_g_tab[i] = (int16) (-(0.114 / 0.331) * CB);
+ Cb_b_tab[i] = (int16) ( (0.587 / 0.331) * CB);
}
- int y, cb, cr;
- int r, g, b;
- int pos = 0;
+ // Set up entries 0-255 in rgb-to-pixel value tables.
- for (cr = 0; cr <= BITDEPTH; cr++) {
- for (cb = 0; cb <= BITDEPTH; cb++) {
- for (y = 0; y < 256; y++) {
- r = ((y - 16) * 256 + (int) (256 * 1.596) * ((cr << SHIFT) - 128)) / 256;
- g = ((y - 16) * 256 - (int) (0.813 * 256) * ((cr << SHIFT) - 128) - (int) (0.391 * 256) * ((cb << SHIFT) - 128)) / 256;
- b = ((y - 16) * 256 + (int) (2.018 * 256) * ((cb << SHIFT) - 128)) / 256;
-
- if (r < 0) r = 0;
- else if (r > 255) r = 255;
- if (g < 0) g = 0;
- else if (g > 255) g = 255;
- if (b < 0) b = 0;
- else if (b > 255) b = 255;
-
- lookup[pos++] = _sys->RGBToColor(r, g, b);
- }
+ if (gBitFormat == 565) {
+ for (i = 0; i < 256; i++) {
+ r_2_pix_alloc[i + 256] = i >> (8 - 5);
+ r_2_pix_alloc[i + 256] <<= 11;
+ g_2_pix_alloc[i + 256] = i >> (8 - 6);
+ g_2_pix_alloc[i + 256] <<= 5;
+ b_2_pix_alloc[i + 256] = i >> (8 - 5);
+ // b_2_pix_alloc[i + 256] <<= 0;
}
+ } else if (gBitFormat == 555) {
+ for (i = 0; i < 256; i++) {
+ r_2_pix_alloc[i + 256] = i >> (8 - 5);
+ r_2_pix_alloc[i + 256] <<= 10;
+ g_2_pix_alloc[i + 256] = i >> (8 - 5);
+ g_2_pix_alloc[i + 256] <<= 5;
+ b_2_pix_alloc[i + 256] = i >> (8 - 5);
+ // b_2_pix_alloc[i + 256] <<= 0;
+ }
+ } else {
+ error("Unknown bit format %d", gBitFormat);
}
-}
-void BaseAnimationState::plotYUV(OverlayColor *lut, int width, int height, byte *const *dat) {
+ // Spread out the values we have to the rest of the array so that we do
+ // not need to check for overflow.
- if (!lut)
- return;
+ for (i = 0; i < 256; i++) {
+ r_2_pix_alloc[i] = r_2_pix_alloc[256];
+ r_2_pix_alloc[i + 512] = r_2_pix_alloc[511];
+ g_2_pix_alloc[i] = g_2_pix_alloc[256];
+ g_2_pix_alloc[i + 512] = g_2_pix_alloc[511];
+ b_2_pix_alloc[i] = b_2_pix_alloc[256];
+ b_2_pix_alloc[i + 512] = b_2_pix_alloc[511];
+ }
+
+ bitFormat = gBitFormat;
+}
+void BaseAnimationState::plotYUV(int width, int height, byte *const *dat) {
OverlayColor *ptr = overlay + (MOVIE_HEIGHT - height) / 2 * MOVIE_WIDTH + (MOVIE_WIDTH - width) / 2;
- int x, y;
+ byte *lum = dat[0];
+ byte *cr = dat[2];
+ byte *cb = dat[1];
- int ypos = 0;
- int cpos = 0;
- int linepos = 0;
+ byte *lum2 = lum + width;
+
+ int16 cr_r;
+ int16 crb_g;
+ int16 cb_b;
+
+ OverlayColor *row1 = ptr;
+ OverlayColor *row2 = ptr + MOVIE_WIDTH;
+
+ int x, y;
for (y = 0; y < height; y += 2) {
for (x = 0; x < width; x += 2) {
- int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * (BITDEPTH+1)) + ((dat[1][cpos] + ROUNDADD)>>SHIFT)) * 256;
- cpos++;
+ register byte L;
- ptr[linepos ] = lut[i + dat[0][ ypos ]];
- ptr[MOVIE_WIDTH + linepos++] = lut[i + dat[0][width + ypos++]];
- ptr[linepos ] = lut[i + dat[0][ ypos ]];
- ptr[MOVIE_WIDTH + linepos++] = lut[i + dat[0][width + ypos++]];
+ cr_r = 0 * 768 + 256 + colortab[*cr + 0 * 256];
+ crb_g = 1 * 768 + 256 + colortab[*cr + 1 * 256] + colortab[*cb + 2 * 256];
+ cb_b = 2 * 768 + 256 + colortab[*cb + 3 * 256];
+ ++cr;
+ ++cb;
+ L = *lum++;
+ *row1++ = (rgb_2_pix[L + cr_r] | rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
+ L = *lum++;
+ *row1++ = (rgb_2_pix[L + cr_r] | rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
+
+ // Now, do second row.
+
+ L = *lum2++;
+ *row2++ = (rgb_2_pix[L + cr_r] | rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
+ L = *lum2++;
+ *row2++ = (rgb_2_pix[L + cr_r] | rgb_2_pix[L + crb_g] | rgb_2_pix[L + cb_b]);
}
- linepos += (2 * MOVIE_WIDTH - width);
- ypos += width;
+
+ // These values are at the start of the next line, (due
+ // to the ++'s above), but they need to be at the start
+ // of the line after that.
+
+ lum += width;
+ lum2 += width;
+ row1 += (2 * MOVIE_WIDTH - width);
+ row2 += (2 * MOVIE_WIDTH - width);
}
}
diff --git a/graphics/animation.h b/graphics/animation.h
index 2aa633d0e2..f59fbae57d 100644
--- a/graphics/animation.h
+++ b/graphics/animation.h
@@ -109,8 +109,10 @@ protected:
byte pal[4 * 256];
} palettes[50];
#else
- static OverlayColor *lookup;
OverlayColor *overlay;
+ int bitFormat;
+ int16 *colortab;
+ uint16 *rgb_2_pix;
#endif
public:
@@ -119,8 +121,9 @@ public:
bool init(const char *name, void *audioArg = NULL);
bool decodeFrame();
+
#ifndef BACKEND_8BIT
- void invalidateLookup(bool rebuild);
+ void buildLookup();
#endif
protected:
@@ -132,8 +135,7 @@ protected:
void buildLookup(int p, int lines);
virtual void setPalette(byte *pal) = 0;
#else
- void buildLookup(void);
- void plotYUV(OverlayColor *lut, int width, int height, byte *const *dat);
+ void plotYUV(int width, int height, byte *const *dat);
#endif
};
diff --git a/sword1/animation.cpp b/sword1/animation.cpp
index 8761454d89..b363ea761f 100644
--- a/sword1/animation.cpp
+++ b/sword1/animation.cpp
@@ -50,7 +50,7 @@ void AnimationState::drawYUV(int width, int height, byte *const *dat) {
#ifdef BACKEND_8BIT
_scr->plotYUV(lut, width, height, dat);
#else
- plotYUV(lookup, width, height, dat);
+ plotYUV(width, height, dat);
#endif
}
@@ -145,7 +145,7 @@ void MoviePlayer::play(uint32 id) {
switch (event.type) {
#ifndef BACKEND_8BIT
case OSystem::EVENT_SCREEN_CHANGED:
- anim->invalidateLookup(true);
+ anim->buildLookup();
break;
#endif
case OSystem::EVENT_KEYDOWN:
diff --git a/sword2/driver/animation.cpp b/sword2/driver/animation.cpp
index 6efa697c4d..6d9a7db779 100644
--- a/sword2/driver/animation.cpp
+++ b/sword2/driver/animation.cpp
@@ -104,7 +104,7 @@ void AnimationState::drawYUV(int width, int height, byte *const *dat) {
#ifdef BACKEND_8BIT
_vm->_screen->plotYUV(lut, width, height, dat);
#else
- plotYUV(lookup, width, height, dat);
+ plotYUV(width, height, dat);
#endif
}
@@ -308,7 +308,7 @@ void MoviePlayer::playMPEG(const char *filename, MovieTextObject *text[], byte *
switch (event.type) {
#ifndef BACKEND_8BIT
case OSystem::EVENT_SCREEN_CHANGED:
- anim->invalidateLookup(true);
+ anim->buildLookup();
break;
#endif
case OSystem::EVENT_KEYDOWN: