aboutsummaryrefslogtreecommitdiff
path: root/video/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'video/codecs')
-rw-r--r--video/codecs/cdtoons.cpp2
-rw-r--r--video/codecs/cinepak.cpp6
-rw-r--r--video/codecs/codec.h2
-rw-r--r--video/codecs/indeo3.cpp119
-rw-r--r--video/codecs/mpeg.cpp107
-rw-r--r--video/codecs/mpeg.h98
-rw-r--r--video/codecs/msrle.cpp2
-rw-r--r--video/codecs/msvideo1.cpp2
-rw-r--r--video/codecs/qtrle.cpp12
-rw-r--r--video/codecs/rpza.cpp2
-rw-r--r--video/codecs/smc.cpp2
11 files changed, 265 insertions, 89 deletions
diff --git a/video/codecs/cdtoons.cpp b/video/codecs/cdtoons.cpp
index 528cee8094..68925ed0db 100644
--- a/video/codecs/cdtoons.cpp
+++ b/video/codecs/cdtoons.cpp
@@ -298,7 +298,7 @@ Graphics::Surface *CDToonsDecoder::decodeImage(Common::SeekableReadStream *strea
for (uint i = 0; i < actions.size(); i++) {
CDToonsAction &action = actions[i];
if (i == 0 && action.blockId == 0)
- memset(_surface->pixels, backgroundColor, _surface->w * _surface->h);
+ memset(_surface->getPixels(), backgroundColor, _surface->w * _surface->h);
if (!_blocks.contains(action.blockId))
continue;
if (!action.rect.right)
diff --git a/video/codecs/cinepak.cpp b/video/codecs/cinepak.cpp
index bcf0cf1180..a7782f4192 100644
--- a/video/codecs/cinepak.cpp
+++ b/video/codecs/cinepak.cpp
@@ -41,11 +41,11 @@ namespace Video {
byte b = _clipTable[lum + (u << 1)]; \
\
if (_pixelFormat.bytesPerPixel == 2) \
- *((uint16 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b); \
+ *((uint16 *)_curFrame.surface->getPixels() + offset) = _pixelFormat.RGBToColor(r, g, b); \
else \
- *((uint32 *)_curFrame.surface->pixels + offset) = _pixelFormat.RGBToColor(r, g, b); \
+ *((uint32 *)_curFrame.surface->getPixels() + offset) = _pixelFormat.RGBToColor(r, g, b); \
} else \
- *((byte *)_curFrame.surface->pixels + offset) = lum
+ *((byte *)_curFrame.surface->getPixels() + offset) = lum
CinepakDecoder::CinepakDecoder(int bitsPerPixel) : Codec() {
_curFrame.surface = NULL;
diff --git a/video/codecs/codec.h b/video/codecs/codec.h
index c1194e461b..a4ad786bb0 100644
--- a/video/codecs/codec.h
+++ b/video/codecs/codec.h
@@ -51,7 +51,7 @@ public:
* containing the decoded frame.
*
* @return a pointer to the decoded frame
- * @note stream is not deleted
+ * @note stream is not deleted
*/
virtual const Graphics::Surface *decodeImage(Common::SeekableReadStream *stream) = 0;
diff --git a/video/codecs/indeo3.cpp b/video/codecs/indeo3.cpp
index 7bf7fc8235..28e1a9c620 100644
--- a/video/codecs/indeo3.cpp
+++ b/video/codecs/indeo3.cpp
@@ -32,8 +32,9 @@
#include "common/endian.h"
#include "common/stream.h"
#include "common/textconsole.h"
+#include "common/util.h"
-#include "graphics/conversion.h"
+#include "graphics/yuv_to_rgb.h"
#include "video/codecs/indeo3.h"
@@ -260,91 +261,61 @@ const Graphics::Surface *Indeo3Decoder::decodeImage(Common::SeekableReadStream *
delete[] inData;
- // Blit the frame onto the surface
const byte *srcY = _cur_frame->Ybuf;
const byte *srcU = _cur_frame->Ubuf;
const byte *srcV = _cur_frame->Vbuf;
- byte *dest = (byte *)_surface->pixels;
-
- const byte *srcUP = srcU;
- const byte *srcVP = srcV;
- const byte *srcUN = srcU + chromaWidth;
- const byte *srcVN = srcV + chromaWidth;
-
- uint32 scaleWidth = _surface->w / fWidth;
- uint32 scaleHeight = _surface->h / fHeight;
- for (uint32 y = 0; y < fHeight; y++) {
- byte *rowDest = dest;
-
- for (uint32 sH = 0; sH < scaleHeight; sH++) {
- for (uint32 x = 0; x < fWidth; x++) {
- uint32 xP = MAX<int32>((x >> 2) - 1, 0);
- uint32 xN = MIN<int32>((x >> 2) + 1, chromaWidth - 1);
-
- byte cY = srcY[x];
- byte cU = srcU[x >> 2];
- byte cV = srcV[x >> 2];
-
- if (((x % 4) == 0) && ((y % 4) == 0)) {
- cU = (((uint32) cU) + ((uint32) srcUP[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[xP])) / 2;
- } else if (((x % 4) == 3) && ((y % 4) == 0)) {
- cU = (((uint32) cU) + ((uint32) srcUP[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[xN])) / 2;
- } else if (((x % 4) == 0) && ((y % 4) == 3)) {
- cU = (((uint32) cU) + ((uint32) srcUN[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[xP])) / 2;
- } else if (((x % 4) == 3) && ((y % 4) == 3)) {
- cU = (((uint32) cU) + ((uint32) srcUN[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[xN])) / 2;
- } else if ( (x % 4) == 0) {
- cU = (((uint32) cU) + ((uint32) srcU[xP])) / 2;
- cV = (((uint32) cV) + ((uint32) srcV[xP])) / 2;
- } else if ( (x % 4) == 3) {
- cU = (((uint32) cU) + ((uint32) srcU[xN])) / 2;
- cV = (((uint32) cV) + ((uint32) srcV[xN])) / 2;
- } else if ( (y % 4) == 0) {
- cU = (((uint32) cU) + ((uint32) srcUP[x >> 2])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVP[x >> 2])) / 2;
- } else if ( (y % 4) == 3) {
- cU = (((uint32) cU) + ((uint32) srcUN[x >> 2])) / 2;
- cV = (((uint32) cV) + ((uint32) srcVN[x >> 2])) / 2;
- }
+ // Create buffers for U/V with an extra row/column copied from the second-to-last
+ // row/column.
+ byte *tempU = new byte[(chromaWidth + 1) * (chromaHeight + 1)];
+ byte *tempV = new byte[(chromaWidth + 1) * (chromaHeight + 1)];
- byte r = 0, g = 0, b = 0;
- Graphics::YUV2RGB(cY, cU, cV, r, g, b);
+ for (uint i = 0; i < chromaHeight; i++) {
+ memcpy(tempU + (chromaWidth + 1) * i, srcU + chromaWidth * i, chromaWidth);
+ memcpy(tempV + (chromaWidth + 1) * i, srcV + chromaWidth * i, chromaWidth);
+ tempU[(chromaWidth + 1) * i + chromaWidth] = srcU[chromaWidth * (i + 1) - 1];
+ tempV[(chromaWidth + 1) * i + chromaWidth] = srcV[chromaWidth * (i + 1) - 1];
+ }
- const uint32 color = _pixelFormat.RGBToColor(r, g, b);
+ memcpy(tempU + (chromaWidth + 1) * chromaHeight, tempU + (chromaWidth + 1) * (chromaHeight - 1),
+ chromaWidth + 1);
+ memcpy(tempV + (chromaWidth + 1) * chromaHeight, tempV + (chromaWidth + 1) * (chromaHeight - 1),
+ chromaWidth + 1);
- for (uint32 sW = 0; sW < scaleWidth; sW++, rowDest += _surface->format.bytesPerPixel) {
- if (_surface->format.bytesPerPixel == 1)
- *((uint8 *)rowDest) = (uint8)color;
- else if (_surface->format.bytesPerPixel == 2)
- *((uint16 *)rowDest) = (uint16)color;
- }
- }
+ // Blit the frame onto the surface
+ uint32 scaleWidth = _surface->w / fWidth;
+ uint32 scaleHeight = _surface->h / fHeight;
- dest += _surface->pitch;
+ if (scaleWidth == 1 && scaleHeight == 1) {
+ // Shortcut: Don't need to scale so we can decode straight to the surface
+ YUVToRGBMan.convert410(_surface, Graphics::YUVToRGBManager::kScaleITU, srcY, tempU, tempV,
+ fWidth, fHeight, fWidth, chromaWidth + 1);
+ } else {
+ // Need to upscale, so decode to a temp surface first
+ Graphics::Surface tempSurface;
+ tempSurface.create(fWidth, fHeight, _surface->format);
+
+ YUVToRGBMan.convert410(&tempSurface, Graphics::YUVToRGBManager::kScaleITU, srcY, tempU, tempV,
+ fWidth, fHeight, fWidth, chromaWidth + 1);
+
+ // Upscale
+ for (int y = 0; y < _surface->h; y++) {
+ for (int x = 0; x < _surface->w; x++) {
+ if (_surface->format.bytesPerPixel == 1)
+ *((byte *)_surface->getBasePtr(x, y)) = *((byte *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ else if (_surface->format.bytesPerPixel == 2)
+ *((uint16 *)_surface->getBasePtr(x, y)) = *((uint16 *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ else if (_surface->format.bytesPerPixel == 4)
+ *((uint32 *)_surface->getBasePtr(x, y)) = *((uint32 *)tempSurface.getBasePtr(x / scaleWidth, y / scaleHeight));
+ }
}
- srcY += fWidth;
-
- if ((y & 3) == 3) {
- srcU += chromaWidth;
- srcV += chromaWidth;
-
- if (y > 0) {
- srcUP += chromaWidth;
- srcVP += chromaWidth;
- }
- if (y < (fHeight - 4U)) {
- srcUN += chromaWidth;
- srcVN += chromaWidth;
- }
- }
+ tempSurface.free();
}
+ delete[] tempU;
+ delete[] tempV;
+
return _surface;
}
diff --git a/video/codecs/mpeg.cpp b/video/codecs/mpeg.cpp
new file mode 100644
index 0000000000..4540b4182e
--- /dev/null
+++ b/video/codecs/mpeg.cpp
@@ -0,0 +1,107 @@
+/* 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.
+ *
+ */
+
+#include "common/debug.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+#include "graphics/surface.h"
+#include "graphics/yuv_to_rgb.h"
+
+#include "video/codecs/mpeg.h"
+
+namespace Video {
+
+MPEGDecoder::MPEGDecoder() : Codec() {
+ _pixelFormat = g_system->getScreenFormat();
+ _surface = 0;
+
+ _mpegDecoder = mpeg2_init();
+
+ if (!_mpegDecoder)
+ error("Could not initialize libmpeg2");
+
+ _mpegInfo = mpeg2_info(_mpegDecoder);
+}
+
+MPEGDecoder::~MPEGDecoder() {
+ mpeg2_close(_mpegDecoder);
+
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ }
+}
+
+const Graphics::Surface *MPEGDecoder::decodeImage(Common::SeekableReadStream *stream) {
+ uint32 framePeriod;
+ decodePacket(stream, framePeriod);
+ return _surface;
+}
+
+bool MPEGDecoder::decodePacket(Common::SeekableReadStream *packet, uint32 &framePeriod, Graphics::Surface *dst) {
+ // Decode as much as we can out of this packet
+ uint32 size = 0xFFFFFFFF;
+ mpeg2_state_t state;
+ bool foundFrame = false;
+ framePeriod = 0;
+
+ do {
+ state = mpeg2_parse(_mpegDecoder);
+
+ switch (state) {
+ case STATE_BUFFER:
+ size = packet->read(_buffer, BUFFER_SIZE);
+ mpeg2_buffer(_mpegDecoder, _buffer, _buffer + size);
+ break;
+ case STATE_SLICE:
+ case STATE_END:
+ if (_mpegInfo->display_fbuf) {
+ foundFrame = true;
+ const mpeg2_sequence_t *sequence = _mpegInfo->sequence;
+
+ framePeriod += sequence->frame_period;
+
+ if (!dst) {
+ // If no destination is specified, use our internal storage
+ if (!_surface) {
+ _surface = new Graphics::Surface();
+ _surface->create(sequence->picture_width, sequence->picture_height, _pixelFormat);
+ }
+
+ dst = _surface;
+ }
+
+ YUVToRGBMan.convert420(dst, Graphics::YUVToRGBManager::kScaleITU, _mpegInfo->display_fbuf->buf[0],
+ _mpegInfo->display_fbuf->buf[1], _mpegInfo->display_fbuf->buf[2], sequence->picture_width,
+ sequence->picture_height, sequence->width, sequence->chroma_width);
+ }
+ break;
+ default:
+ break;
+ }
+ } while (size != 0);
+
+ return foundFrame;
+}
+
+} // End of namespace Video
diff --git a/video/codecs/mpeg.h b/video/codecs/mpeg.h
new file mode 100644
index 0000000000..0082844537
--- /dev/null
+++ b/video/codecs/mpeg.h
@@ -0,0 +1,98 @@
+/* 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.
+ *
+ */
+
+#ifdef USE_MPEG2
+
+#ifndef VIDEO_CODECS_MPEG_H
+#define VIDEO_CODECS_MPEG_H
+
+#include "video/codecs/codec.h"
+#include "graphics/pixelformat.h"
+
+#if defined(__PLAYSTATION2__)
+ typedef uint8 uint8_t;
+ typedef uint16 uint16_t;
+ typedef uint32 uint32_t;
+#elif defined(_WIN32_WCE)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+#elif defined(_MSC_VER)
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ #if !defined(SDL_COMPILEDVERSION) || (SDL_COMPILEDVERSION < 1210)
+ typedef signed long int32_t;
+ typedef unsigned long uint32_t;
+ #endif
+#else
+# include <inttypes.h>
+#endif
+
+extern "C" {
+ #include <mpeg2dec/mpeg2.h>
+}
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace Video {
+
+// MPEG 1/2 video decoder
+
+class MPEGDecoder : public Codec {
+public:
+ MPEGDecoder();
+ ~MPEGDecoder();
+
+ // Codec interface
+ const Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
+ Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
+
+ // MPEGPSDecoder call
+ bool decodePacket(Common::SeekableReadStream *packet, uint32 &framePeriod, Graphics::Surface *dst = 0);
+
+private:
+ Graphics::PixelFormat _pixelFormat;
+ Graphics::Surface *_surface;
+
+ enum {
+ BUFFER_SIZE = 4096
+ };
+
+ byte _buffer[BUFFER_SIZE];
+ mpeg2dec_t *_mpegDecoder;
+ const mpeg2_info_t *_mpegInfo;
+};
+
+} // End of namespace Video
+
+#endif // VIDEO_CODECS_MPEG_H
+
+#endif // USE_MPEG2
diff --git a/video/codecs/msrle.cpp b/video/codecs/msrle.cpp
index fa03a59efd..2f2ac0334f 100644
--- a/video/codecs/msrle.cpp
+++ b/video/codecs/msrle.cpp
@@ -53,7 +53,7 @@ void MSRLEDecoder::decode8(Common::SeekableReadStream *stream) {
int x = 0;
int y = _surface->h - 1;
- byte *data = (byte *) _surface->pixels;
+ byte *data = (byte *) _surface->getPixels();
uint16 width = _surface->w;
uint16 height = _surface->h;
diff --git a/video/codecs/msvideo1.cpp b/video/codecs/msvideo1.cpp
index 06e4640025..409d588ddf 100644
--- a/video/codecs/msvideo1.cpp
+++ b/video/codecs/msvideo1.cpp
@@ -48,7 +48,7 @@ MSVideo1Decoder::~MSVideo1Decoder() {
void MSVideo1Decoder::decode8(Common::SeekableReadStream *stream) {
byte colors[8];
- byte *pixels = (byte *)_surface->pixels;
+ byte *pixels = (byte *)_surface->getPixels();
uint16 stride = _surface->w;
int skipBlocks = 0;
diff --git a/video/codecs/qtrle.cpp b/video/codecs/qtrle.cpp
index d2cdea27de..1f1fee7997 100644
--- a/video/codecs/qtrle.cpp
+++ b/video/codecs/qtrle.cpp
@@ -61,7 +61,7 @@ QTRLEDecoder::QTRLEDecoder(uint16 width, uint16 height, byte bitsPerPixel) : Cod
void QTRLEDecoder::decode1(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- byte *rgb = (byte *)_surface->pixels;
+ byte *rgb = (byte *)_surface->getPixels();
while (linesToChange) {
CHECK_STREAM_PTR(2);
@@ -105,7 +105,7 @@ void QTRLEDecoder::decode1(Common::SeekableReadStream *stream, uint32 rowPtr, ui
void QTRLEDecoder::decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange, byte bpp) {
uint32 pixelPtr = 0;
- byte *rgb = (byte *)_surface->pixels;
+ byte *rgb = (byte *)_surface->getPixels();
byte numPixels = (bpp == 4) ? 8 : 16;
while (linesToChange--) {
@@ -165,7 +165,7 @@ void QTRLEDecoder::decode2_4(Common::SeekableReadStream *stream, uint32 rowPtr,
void QTRLEDecoder::decode8(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- byte *rgb = (byte *)_surface->pixels;
+ byte *rgb = (byte *)_surface->getPixels();
while (linesToChange--) {
CHECK_STREAM_PTR(2);
@@ -210,7 +210,7 @@ void QTRLEDecoder::decode8(Common::SeekableReadStream *stream, uint32 rowPtr, ui
void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- uint16 *rgb = (uint16 *)_surface->pixels;
+ uint16 *rgb = (uint16 *)_surface->getPixels();
while (linesToChange--) {
CHECK_STREAM_PTR(2);
@@ -248,7 +248,7 @@ void QTRLEDecoder::decode16(Common::SeekableReadStream *stream, uint32 rowPtr, u
void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- uint32 *rgb = (uint32 *)_surface->pixels;
+ uint32 *rgb = (uint32 *)_surface->getPixels();
while (linesToChange--) {
CHECK_STREAM_PTR(2);
@@ -294,7 +294,7 @@ void QTRLEDecoder::decode24(Common::SeekableReadStream *stream, uint32 rowPtr, u
void QTRLEDecoder::decode32(Common::SeekableReadStream *stream, uint32 rowPtr, uint32 linesToChange) {
uint32 pixelPtr = 0;
- uint32 *rgb = (uint32 *)_surface->pixels;
+ uint32 *rgb = (uint32 *)_surface->getPixels();
while (linesToChange--) {
CHECK_STREAM_PTR(2);
diff --git a/video/codecs/rpza.cpp b/video/codecs/rpza.cpp
index 0a9f87747e..17a2c53d9b 100644
--- a/video/codecs/rpza.cpp
+++ b/video/codecs/rpza.cpp
@@ -58,7 +58,7 @@ RPZADecoder::~RPZADecoder() {
#define PUT_PIXEL(color) \
if ((int32)blockPtr < _surface->w * _surface->h) \
- WRITE_UINT16((uint16 *)_surface->pixels + blockPtr, color); \
+ WRITE_UINT16((uint16 *)_surface->getPixels() + blockPtr, color); \
blockPtr++
const Graphics::Surface *RPZADecoder::decodeImage(Common::SeekableReadStream *stream) {
diff --git a/video/codecs/smc.cpp b/video/codecs/smc.cpp
index 2eedb62a0f..c0f8152547 100644
--- a/video/codecs/smc.cpp
+++ b/video/codecs/smc.cpp
@@ -56,7 +56,7 @@ SMCDecoder::~SMCDecoder() {
}
const Graphics::Surface *SMCDecoder::decodeImage(Common::SeekableReadStream *stream) {
- byte *pixels = (byte *)_surface->pixels;
+ byte *pixels = (byte *)_surface->getPixels();
uint32 numBlocks = 0;
uint32 colorFlags = 0;