aboutsummaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/avi_decoder.cpp68
-rw-r--r--video/avi_decoder.h7
-rw-r--r--video/codecs/mpeg.cpp107
-rw-r--r--video/codecs/mpeg.h98
-rw-r--r--video/module.mk5
5 files changed, 264 insertions, 21 deletions
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index 6fe9c773b8..ff728a8437 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -36,6 +36,7 @@
// Video Codecs
#include "video/codecs/cinepak.h"
#include "video/codecs/indeo3.h"
+#include "video/codecs/mpeg.h"
#include "video/codecs/msvideo1.h"
#include "video/codecs/msrle.h"
#include "video/codecs/truemotion1.h"
@@ -64,8 +65,8 @@ namespace Video {
#define ID_VEDT MKTAG('v','e','d','t')
#define ID_IDX1 MKTAG('i','d','x','1')
#define ID_STRD MKTAG('s','t','r','d')
-#define ID_00AM MKTAG('0','0','A','M')
//#define ID_INFO MKTAG('I','N','F','O')
+#define ID_ISFT MKTAG('I','S','F','T')
// Codec tags
#define ID_RLE MKTAG('R','L','E',' ')
@@ -75,6 +76,7 @@ namespace Video {
#define ID_CVID MKTAG('c','v','i','d')
#define ID_IV32 MKTAG('i','v','3','2')
#define ID_DUCK MKTAG('D','U','C','K')
+#define ID_MPG2 MKTAG('m','p','g','2')
static byte char2num(char c) {
c = tolower((byte)c);
@@ -89,17 +91,27 @@ static uint16 getStreamType(uint32 tag) {
return tag & 0xffff;
}
-AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _soundType(soundType) {
- _decodedHeader = false;
- _fileStream = 0;
- memset(&_ixInfo, 0, sizeof(_ixInfo));
- memset(&_header, 0, sizeof(_header));
+AVIDecoder::AVIDecoder(Audio::Mixer::SoundType soundType) : _frameRateOverride(0), _soundType(soundType) {
+ initCommon();
+}
+
+AVIDecoder::AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType)
+ : _frameRateOverride(frameRateOverride), _soundType(soundType) {
+ initCommon();
}
AVIDecoder::~AVIDecoder() {
close();
}
+void AVIDecoder::initCommon() {
+ _decodedHeader = false;
+ _foundMovieList = false;
+ _fileStream = 0;
+ memset(&_ixInfo, 0, sizeof(_ixInfo));
+ memset(&_header, 0, sizeof(_header));
+}
+
void AVIDecoder::runHandle(uint32 tag) {
assert(_fileStream);
if (_fileStream->eos())
@@ -137,6 +149,7 @@ void AVIDecoder::runHandle(uint32 tag) {
case ID_STRD: // Extra stream info, safe to ignore
case ID_VEDT: // Unknown, safe to ignore
case ID_JUNK: // Alignment bytes, should be ignored
+ case ID_ISFT: // Metadata, safe to ignore
{
uint32 junkSize = _fileStream->readUint32LE();
_fileStream->skip(junkSize + (junkSize & 1)); // Alignment
@@ -165,6 +178,13 @@ void AVIDecoder::handleList() {
debug(0, "Found LIST of type %s", tag2str(listType));
+ if (listType == ID_MOVI) {
+ // Found the 'movi' list
+ // We're done parsing everything
+ _foundMovieList = true;
+ return;
+ }
+
while ((_fileStream->pos() - curPos) < listSize)
runHandle(_fileStream->readUint32BE());
@@ -203,6 +223,11 @@ void AVIDecoder::handleStreamHeader() {
uint32 startPos = _fileStream->pos();
if (sHeader.streamType == ID_VIDS) {
+ if (_frameRateOverride != 0) {
+ sHeader.rate = _frameRateOverride.getNumerator();
+ sHeader.scale = _frameRateOverride.getDenominator();
+ }
+
BitmapInfoHeader bmInfo;
bmInfo.size = _fileStream->readUint32LE();
bmInfo.width = _fileStream->readUint32LE();
@@ -263,26 +288,24 @@ bool AVIDecoder::loadStream(Common::SeekableReadStream *stream) {
_fileStream = stream;
_decodedHeader = false;
+ _foundMovieList = false;
// Read chunks until we have decoded the header
- while (!_decodedHeader)
+ while (!_decodedHeader && _fileStream->pos() < _fileStream->size())
runHandle(_fileStream->readUint32BE());
- uint32 nextTag = _fileStream->readUint32BE();
-
- // Throw out any JUNK section
- if (nextTag == ID_JUNK) {
- runHandle(ID_JUNK);
- nextTag = _fileStream->readUint32BE();
+ if (_fileStream->pos() >= _fileStream->size()) {
+ warning("Failed to find AVI header");
+ return false;
}
- // Ignore the 'movi' LIST
- if (nextTag == ID_LIST) {
- _fileStream->readUint32BE(); // Skip size
- if (_fileStream->readUint32BE() != ID_MOVI)
- error("Expected 'movi' LIST");
- } else {
- error("Expected 'movi' LIST");
+ // Then read until we find the movie list
+ while (!_foundMovieList && _fileStream->pos() < _fileStream->size())
+ runHandle(_fileStream->readUint32BE());
+
+ if (_fileStream->pos() >= _fileStream->size()) {
+ warning("Failed to find AVI 'movi' LIST");
+ return false;
}
return true;
@@ -294,6 +317,7 @@ void AVIDecoder::close() {
delete _fileStream;
_fileStream = 0;
_decodedHeader = false;
+ _foundMovieList = false;
delete[] _ixInfo.indices;
memset(&_ixInfo, 0, sizeof(_ixInfo));
@@ -428,6 +452,10 @@ Codec *AVIDecoder::AVIVideoTrack::createCodec() {
case ID_DUCK:
return new TrueMotion1Decoder(_bmInfo.width, _bmInfo.height);
#endif
+#ifdef USE_MPEG2
+ case ID_MPG2:
+ return new MPEGDecoder();
+#endif
default:
warning("Unknown/Unhandled compression format \'%s\'", tag2str(_vidsHeader.streamHandler));
}
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 34a67f4c28..6082232464 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -52,10 +52,13 @@ class Codec;
*
* Video decoder used in engines:
* - sci
+ * - sword1
+ * - sword2
*/
class AVIDecoder : public VideoDecoder {
public:
AVIDecoder(Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
+ AVIDecoder(const Common::Rational &frameRateOverride, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
virtual ~AVIDecoder();
bool loadStream(Common::SeekableReadStream *stream);
@@ -219,9 +222,11 @@ private:
AVIHeader _header;
Common::SeekableReadStream *_fileStream;
- bool _decodedHeader;
+ bool _decodedHeader, _foundMovieList;
Audio::Mixer::SoundType _soundType;
+ Common::Rational _frameRateOverride;
+ void initCommon();
void runHandle(uint32 tag);
void handleList();
diff --git a/video/codecs/mpeg.cpp b/video/codecs/mpeg.cpp
new file mode 100644
index 0000000000..cb3c63fcfc
--- /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/module.mk b/video/module.mk
index 287e14ce18..a491947aaf 100644
--- a/video/module.mk
+++ b/video/module.mk
@@ -31,5 +31,10 @@ MODULE_OBJS += \
theora_decoder.o
endif
+ifdef USE_MPEG2
+MODULE_OBJS += \
+ codecs/mpeg.o
+endif
+
# Include common rules
include $(srcdir)/rules.mk