diff options
-rw-r--r-- | engines/sword25/fmv/theora_decoder.cpp | 48 | ||||
-rw-r--r-- | graphics/module.mk | 3 | ||||
-rw-r--r-- | graphics/yuv_to_rgb.cpp | 240 | ||||
-rw-r--r-- | graphics/yuv_to_rgb.h | 40 |
4 files changed, 285 insertions, 46 deletions
diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp index 4f5a006770..9aa7ead385 100644 --- a/engines/sword25/fmv/theora_decoder.cpp +++ b/engines/sword25/fmv/theora_decoder.cpp @@ -39,7 +39,8 @@ #ifdef USE_THEORADEC #include "common/system.h" #include "common/textconsole.h" -#include "graphics/conversion.h" +#include "common/util.h" +#include "graphics/yuv_to_rgb.h" #include "audio/decoders/raw.h" #include "sword25/kernel/common.h" @@ -508,16 +509,6 @@ uint32 TheoraDecoder::getElapsedTime() const { return VideoDecoder::getElapsedTime(); } -static void convertYUVtoBGRA(int y, int u, int v, byte *dst, Graphics::PixelFormat format) { - byte r, g, b; - Graphics::YUV2RGB(y, u, v, r, g, b); - - if (format.bytesPerPixel == 2) - *((uint16 *)dst) = format.RGBToColor(r, g, b); - else - *((uint32 *)dst) = format.RGBToColor(r, g, b); -} - enum TheoraYUVBuffers { kBufferY = 0, kBufferU = 1, @@ -537,40 +528,7 @@ void TheoraDecoder::translateYUVtoRGBA(th_ycbcr_buffer &YUVBuffer) { assert(YUVBuffer[kBufferU].height == YUVBuffer[kBufferY].height >> 1); assert(YUVBuffer[kBufferV].height == YUVBuffer[kBufferY].height >> 1); - const byte *ySrc = YUVBuffer[kBufferY].data; - const byte *uSrc = YUVBuffer[kBufferU].data; - const byte *vSrc = YUVBuffer[kBufferV].data; - byte *dst = (byte *)_surface->pixels; - int u = 0, v = 0; - - const int blockSize = YUVBuffer[kBufferY].width * getPixelFormat().bytesPerPixel; - const int halfHeight = YUVBuffer[kBufferY].height >> 1; - const int halfWidth = YUVBuffer[kBufferY].width >> 1; - const int yStep = (YUVBuffer[kBufferY].stride << 1) - YUVBuffer[kBufferY].width; - // The UV step is usually 0, since in most cases stride == width. - // The asserts at the top ensure that the U and V steps are equal - // (and they must always be equal) - const int uvStep = YUVBuffer[kBufferU].stride - YUVBuffer[kBufferU].width; - const int stride = YUVBuffer[kBufferY].stride; - - for (int h = 0; h < halfHeight; ++h) { - for (int w = 0; w < halfWidth; ++w) { - u = *uSrc++; - v = *vSrc++; - - for (int i = 0; i <= 1; i++) { - convertYUVtoBGRA(*ySrc, u, v, dst, getPixelFormat()); - convertYUVtoBGRA(*(ySrc + stride), u, v, dst + blockSize, getPixelFormat()); - ySrc++; - dst += 4; // BGRA - } - } - - dst += blockSize; - ySrc += yStep; - uSrc += uvStep; - vSrc += uvStep; - } + Graphics::convertYUV420ToRGB(_surface, YUVBuffer[kBufferY].data, YUVBuffer[kBufferU].data, YUVBuffer[kBufferV].data, YUVBuffer[kBufferY].width, YUVBuffer[kBufferY].height, YUVBuffer[kBufferY].stride, YUVBuffer[kBufferU].stride); } } // End of namespace Sword25 diff --git a/graphics/module.mk b/graphics/module.mk index 59621dc525..a9051c868a 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -25,7 +25,8 @@ MODULE_OBJS := \ thumbnail.o \ VectorRenderer.o \ VectorRendererSpec.o \ - wincursor.o + wincursor.o \ + yuv_to_rgb.o ifdef USE_SCALERS MODULE_OBJS += \ diff --git a/graphics/yuv_to_rgb.cpp b/graphics/yuv_to_rgb.cpp new file mode 100644 index 0000000000..b1107a7475 --- /dev/null +++ b/graphics/yuv_to_rgb.cpp @@ -0,0 +1,240 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// 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 +// buildLookup() and plotYUV*() functions 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. + +#include "common/scummsys.h" +#include "common/singleton.h" + +#include "graphics/surface.h" + +namespace Graphics { + +class YUVToRGBLookup { +public: + YUVToRGBLookup(Graphics::PixelFormat format); + ~YUVToRGBLookup(); + + int16 *_colorTab; + uint32 *_rgbToPix; +}; + +YUVToRGBLookup::YUVToRGBLookup(Graphics::PixelFormat format) { + _colorTab = new int16[4 * 256]; // 2048 bytes + + 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]; + + _rgbToPix = new uint32[3 * 768]; // 9216 bytes + + uint32 *r_2_pix_alloc = &_rgbToPix[0 * 768]; + uint32 *g_2_pix_alloc = &_rgbToPix[1 * 768]; + uint32 *b_2_pix_alloc = &_rgbToPix[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) + 0 * 768 + 256; + Cr_g_tab[i] = (int16) (-(0.299 / 0.419) * CR) + 1 * 768 + 256; + Cb_g_tab[i] = (int16) (-(0.114 / 0.331) * CB); + Cb_b_tab[i] = (int16) ( (0.587 / 0.331) * CB) + 2 * 768 + 256; + } + + // Set up entries 0-255 in rgb-to-pixel value tables. + for (i = 0; i < 256; i++) { + r_2_pix_alloc[i + 256] = format.RGBToColor(i, 0, 0); + g_2_pix_alloc[i + 256] = format.RGBToColor(0, i, 0); + b_2_pix_alloc[i + 256] = format.RGBToColor(0, 0, i); + } + + // Spread out the values we have to the rest of the array so that we do + // not need to check for overflow. + 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]; + } +} + +YUVToRGBLookup::~YUVToRGBLookup() { + delete[] _rgbToPix; + delete[] _colorTab; +} + +class YUVToRGBManager : public Common::Singleton<YUVToRGBManager> { +public: + const YUVToRGBLookup *getLookup(Graphics::PixelFormat format); + +private: + friend class Common::Singleton<SingletonBaseType>; + YUVToRGBManager(); + ~YUVToRGBManager(); + + Graphics::PixelFormat _lastFormat; + YUVToRGBLookup *_lookup; +}; + +YUVToRGBManager::YUVToRGBManager() { + _lookup = 0; +} + +YUVToRGBManager::~YUVToRGBManager() { + delete _lookup; +} + +const YUVToRGBLookup *YUVToRGBManager::getLookup(Graphics::PixelFormat format) { + if (_lastFormat == format) + return _lookup; + + delete _lookup; + _lookup = new YUVToRGBLookup(format); + _lastFormat = format; + return _lookup; +} + +} // End of namespace Graphics + +DECLARE_SINGLETON(Graphics::YUVToRGBManager); + +#define YUVToRGBMan (Graphics::YUVToRGBManager::instance()) + +namespace Graphics { + +#define PUT_PIXEL(s, d) \ + L = &lookup->_rgbToPix[(s)]; \ + if (dst->format.bytesPerPixel == 2) \ + *((uint16 *)(d)) = (L[cr_r] | L[crb_g] | L[cb_b]); \ + else \ + *((uint32 *)(d)) = (L[cr_r] | L[crb_g] | L[cb_b]) + +void convertYUV420ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch) { + const YUVToRGBLookup *lookup = YUVToRGBMan.getLookup(dst->format); + + byte *dstPtr = (byte *)dst->pixels; + + int halfHeight = yHeight >> 1; + int halfWidth = yWidth >> 1; + + for (int h = 0; h < halfHeight; h++) { + for (int w = 0; w < halfWidth; w++) { + register uint32 *L; + + int16 cr_r = lookup->_colorTab[*vSrc + 0 * 256]; + int16 crb_g = lookup->_colorTab[*vSrc + 1 * 256] + lookup->_colorTab[*uSrc + 2 * 256]; + int16 cb_b = lookup->_colorTab[*uSrc + 3 * 256]; + ++uSrc; + ++vSrc; + + PUT_PIXEL(*ySrc, dstPtr); + PUT_PIXEL(*(ySrc + yPitch), dstPtr + dst->pitch); + ySrc++; + dstPtr += dst->format.bytesPerPixel; + PUT_PIXEL(*ySrc, dstPtr); + PUT_PIXEL(*(ySrc + yPitch), dstPtr + dst->pitch); + ySrc++; + dstPtr += dst->format.bytesPerPixel; + } + + dstPtr += dst->pitch; + ySrc += (yPitch << 1) - yWidth; + uSrc += uvPitch - halfWidth; + vSrc += uvPitch - halfWidth; + } +} + +} // End of namespace Graphics diff --git a/graphics/yuv_to_rgb.h b/graphics/yuv_to_rgb.h new file mode 100644 index 0000000000..30f64ee570 --- /dev/null +++ b/graphics/yuv_to_rgb.h @@ -0,0 +1,40 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GRAPHICS_YUV_TO_RGB_H +#define GRAPHICS_YUV_TO_RGB_H + +#include "common/scummsys.h" +#include "graphics/surface.h" + +namespace Graphics { + +struct Surface; + +void convertYUV420ToRGB(Graphics::Surface *dst, const byte *ySrc, const byte *uSrc, const byte *vSrc, int yWidth, int yHeight, int yPitch, int uvPitch); + +} // End of namespace Graphics + +#endif |