aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclone27272013-07-05 15:28:06 -0700
committerclone27272013-07-05 15:28:06 -0700
commit279c9f78412d9053a60b53b70b5e770159a2aa92 (patch)
tree431fdb6ff27fa016dad730c526b89db54becc1f3
parent2521449e79e6650a8663e0143d60d69239e58da8 (diff)
parent4ed1bc3a57e0160eb0b395c2a363151700216d04 (diff)
downloadscummvm-rg350-279c9f78412d9053a60b53b70b5e770159a2aa92.tar.gz
scummvm-rg350-279c9f78412d9053a60b53b70b5e770159a2aa92.tar.bz2
scummvm-rg350-279c9f78412d9053a60b53b70b5e770159a2aa92.zip
Merge pull request #343 from clone2727/mpeg2-avi
Add back support for sword1/2 MPEG-2 cutscenes
-rwxr-xr-xconfigure57
-rw-r--r--engines/sword1/animation.cpp56
-rw-r--r--engines/sword1/animation.h3
-rw-r--r--engines/sword2/animation.cpp55
-rw-r--r--engines/sword2/animation.h3
-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
10 files changed, 393 insertions, 66 deletions
diff --git a/configure b/configure
index e59a38b8a5..22f2377167 100755
--- a/configure
+++ b/configure
@@ -113,6 +113,7 @@ _seq_midi=auto
_sndio=auto
_timidity=auto
_zlib=auto
+_mpeg2=auto
_sparkle=auto
_png=auto
_theoradec=auto
@@ -925,6 +926,9 @@ Optional Libraries:
--with-zlib-prefix=DIR Prefix where zlib is installed (optional)
--disable-zlib disable zlib (compression) support [autodetect]
+ --with-mpeg2-prefix=DIR Prefix where libmpeg2 is installed (optional)
+ --enable-mpeg2 enable mpeg2 codec for cutscenes [autodetect]
+
--with-opengl-prefix=DIR Prefix where OpenGL (ES) is installed (optional)
--disable-opengl disable OpenGL (ES) support [autodetect]
@@ -1005,6 +1009,8 @@ for ac_option in $@; do
--disable-sparkle) _sparkle=no ;;
--enable-nasm) _nasm=yes ;;
--disable-nasm) _nasm=no ;;
+ --enable-mpeg2) _mpeg2=yes ;;
+ --disable-mpeg2) _mpeg2=no ;;
--disable-png) _png=no ;;
--enable-png) _png=yes ;;
--disable-theoradec) _theoradec=no ;;
@@ -1046,6 +1052,11 @@ for ac_option in $@; do
FLUIDSYNTH_CFLAGS="-I$arg/include"
FLUIDSYNTH_LIBS="-L$arg/lib"
;;
+ --with-mpeg2-prefix=*)
+ arg=`echo $ac_option | cut -d '=' -f 2`
+ MPEG2_CFLAGS="-I$arg/include"
+ MPEG2_LIBS="-L$arg/lib"
+ ;;
--with-alsa-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
ALSA_CFLAGS="-I$arg/include"
@@ -3456,6 +3467,52 @@ define_in_config_if_yes "$_zlib" 'USE_ZLIB'
echo "$_zlib"
#
+# Check for LibMPEG2
+#
+echocheck "libmpeg2 >= 0.4.0"
+if test "$_mpeg2" = auto ; then
+ _mpeg2=no
+ cat > $TMPC << EOF
+typedef signed $type_1_byte int8_t;
+typedef signed $type_2_byte int16_t;
+typedef signed $type_4_byte int32_t;
+
+typedef unsigned $type_1_byte uint8_t;
+typedef unsigned $type_2_byte uint16_t;
+typedef unsigned $type_4_byte uint32_t;
+
+extern "C" {
+#include <mpeg2dec/mpeg2.h>
+}
+
+int main(void) {
+ #if MPEG2_RELEASE < MPEG2_VERSION(0, 4, 0)
+ #error libmpeg2 version too low
+ #endif
+
+ /* mpeg2_state_t first appears in 0.4.0 */
+ mpeg2_state_t state;
+
+ return 0;
+}
+EOF
+
+ if test -n "$_host"; then
+ # don't execute while cross compiling
+ cc_check $MPEG2_CFLAGS $MPEG2_LIBS -lmpeg2 && _mpeg2=yes
+ else
+ cc_check_no_clean $MPEG2_CFLAGS $MPEG2_LIBS -lmpeg2 && $TMPO$HOSTEXEEXT && _mpeg2=yes
+ cc_check_clean
+ fi
+fi
+if test "$_mpeg2" = yes ; then
+ INCLUDES="$INCLUDES $MPEG2_CFLAGS"
+ LIBS="$LIBS $MPEG2_LIBS -lmpeg2"
+fi
+define_in_config_if_yes "$_mpeg2" 'USE_MPEG2'
+echo "$_mpeg2"
+
+#
# Check for Sparkle if updates support is enabled
#
echocheck "Sparkle"
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 206bd68b07..79ec060bc1 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -37,7 +37,14 @@
#include "gui/message.h"
+#ifdef USE_MPEG2
+#include "video/avi_decoder.h"
+#endif
+
+#ifdef USE_ZLIB
#include "video/dxa_decoder.h"
+#endif
+
#include "video/psx_decoder.h"
#include "video/smk_decoder.h"
@@ -176,27 +183,26 @@ bool MoviePlayer::load(uint32 id) {
break;
case kVideoDecoderPSX:
filename = Common::String::format("%s.str", (_vm->_systemVars.isDemo) ? sequenceList[id] : sequenceListPSX[id]);
+ break;
+ case kVideoDecoderMP2:
+ filename = Common::String::format("%s.mp2", sequenceList[id]);
+ break;
+ }
- // Need to switch to true color
+ // Need to switch to true color for PSX/MP2 videos
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0);
- // Need to load here in case it fails in which case we'd need
- // to go back to paletted mode
- if (_decoder->loadFile(filename)) {
- _decoder->start();
- return true;
- } else {
+ if (!_decoder->loadFile(filename)) {
+ // Go back to 8bpp color
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
initGraphics(g_system->getWidth(), g_system->getHeight(), true);
- return false;
- }
- break;
- }
- if (!_decoder->loadFile(filename))
return false;
+ }
- // For DXA, also add the external sound file
- if (_decoderType == kVideoDecoderDXA)
+ // For DXA/MP2, also add the external sound file
+ if (_decoderType == kVideoDecoderDXA || _decoderType == kVideoDecoderMP2)
_decoder->addStreamFileTrack(sequenceList[id]);
_decoder->start();
@@ -224,9 +230,9 @@ void MoviePlayer::play() {
}
void MoviePlayer::performPostProcessing(byte *screen) {
- // TODO: We don't support the PSX stream videos yet
+ // TODO: We don't support displaying these in true color yet,
// nor using the PSX fonts to display subtitles.
- if (_vm->isPsx())
+ if (_vm->isPsx() || _decoderType == kVideoDecoderMP2)
return;
if (!_movieTexts.empty()) {
@@ -414,20 +420,19 @@ bool MoviePlayer::playVideo() {
_vm->_system->delayMillis(10);
}
- if (_decoderType == kVideoDecoderPSX) {
- // Need to jump back to paletted color
+ // Need to jump back to paletted color
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
initGraphics(g_system->getWidth(), g_system->getHeight(), true);
- }
return !_vm->shouldQuit() && !skipped;
}
uint32 MoviePlayer::getBlackColor() {
- return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black;
+ return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black;
}
uint32 MoviePlayer::findTextColor() {
- if (_decoderType == kVideoDecoderPSX) {
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) {
// We're in true color mode, so return the actual colors
switch (_textColor) {
case 1:
@@ -547,9 +552,16 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
filename = Common::String::format("%s.mp2", sequenceList[id]);
if (Common::File::exists(filename)) {
- GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK"));
+#ifdef USE_MPEG2
+ // HACK: Old ScummVM builds ignored the AVI frame rate field and forced the video
+ // to be played back at 12fps.
+ Video::VideoDecoder *aviDecoder = new Video::AVIDecoder(12);
+ return new MoviePlayer(vm, textMan, resMan, system, aviDecoder, kVideoDecoderMP2);
+#else
+ GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2"), _("OK"));
dialog.runModal();
return 0;
+#endif
}
if (!vm->isPsx() || scumm_stricmp(sequenceList[id], "enddemo") != 0) {
diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h
index d0c61f5eb3..2c51a74f71 100644
--- a/engines/sword1/animation.h
+++ b/engines/sword1/animation.h
@@ -41,7 +41,8 @@ namespace Sword1 {
enum DecoderType {
kVideoDecoderDXA = 0,
kVideoDecoderSMK = 1,
- kVideoDecoderPSX = 2
+ kVideoDecoderPSX = 2,
+ kVideoDecoderMP2 = 3
};
class MovieText {
diff --git a/engines/sword2/animation.cpp b/engines/sword2/animation.cpp
index 00260f789a..713120ad43 100644
--- a/engines/sword2/animation.cpp
+++ b/engines/sword2/animation.cpp
@@ -42,7 +42,14 @@
#include "gui/message.h"
+#ifdef USE_MPEG2
+#include "video/avi_decoder.h"
+#endif
+
+#ifdef USE_ZLIB
#include "video/dxa_decoder.h"
+#endif
+
#include "video/smk_decoder.h"
#include "video/psx_decoder.h"
@@ -88,26 +95,26 @@ bool MoviePlayer::load(const char *name) {
break;
case kVideoDecoderPSX:
filename = Common::String::format("%s.str", name);
+ break;
+ case kVideoDecoderMP2:
+ filename = Common::String::format("%s.mp2", name);
+ break;
+ }
- // Need to switch to true color
- initGraphics(640, 480, true, 0);
+ // Need to switch to true color for PSX/MP2 videos
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
+ initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0);
- // Need to load here in case it fails in which case we'd need
- // to go back to paletted mode
- if (_decoder->loadFile(filename)) {
- _decoder->start();
- return true;
- } else {
- initGraphics(640, 480, true);
- return false;
- }
- }
+ if (!_decoder->loadFile(filename)) {
+ // Go back to 8bpp color
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
+ initGraphics(g_system->getWidth(), g_system->getHeight(), true);
- if (!_decoder->loadFile(filename))
return false;
+ }
- // For DXA, also add the external sound file
- if (_decoderType == kVideoDecoderDXA)
+ // For DXA/MP2, also add the external sound file
+ if (_decoderType == kVideoDecoderDXA || _decoderType == kVideoDecoderMP2)
_decoder->addStreamFileTrack(name);
_decoder->start();
@@ -136,10 +143,9 @@ void MoviePlayer::play(MovieText *movieTexts, uint32 numMovieTexts, uint32 leadI
_vm->_sound->stopSpeech();
}
- if (_decoderType == kVideoDecoderPSX) {
- // Need to jump back to paletted color
+ // Need to jump back to paletted color
+ if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
initGraphics(640, 480, true);
- }
}
void MoviePlayer::openTextObject(uint32 index) {
@@ -378,11 +384,11 @@ bool MoviePlayer::playVideo() {
}
uint32 MoviePlayer::getBlackColor() {
- return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black;
+ return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0x00, 0x00, 0x00) : _black;
}
uint32 MoviePlayer::getWhiteColor() {
- return (_decoderType == kVideoDecoderPSX) ? g_system->getScreenFormat().RGBToColor(0xFF, 0xFF, 0xFF) : _white;
+ return (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2) ? g_system->getScreenFormat().RGBToColor(0xFF, 0xFF, 0xFF) : _white;
}
void MoviePlayer::drawFramePSX(const Graphics::Surface *frame) {
@@ -446,9 +452,16 @@ MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, OSystem *system
filename = Common::String::format("%s.mp2", name);
if (Common::File::exists(filename)) {
- GUI::MessageDialog dialog(_("MPEG2 cutscenes are no longer supported"), _("OK"));
+#ifdef USE_MPEG2
+ // HACK: Old ScummVM builds ignored the AVI frame rate field and forced the video
+ // to be played back at 12fps.
+ Video::AVIDecoder *aviDecoder = new Video::AVIDecoder(12);
+ return new MoviePlayer(vm, system, aviDecoder, kVideoDecoderMP2);
+#else
+ GUI::MessageDialog dialog(_("MPEG-2 cutscenes found but ScummVM has been built without MPEG-2 support"), _("OK"));
dialog.runModal();
return NULL;
+#endif
}
// The demo tries to play some cutscenes that aren't there, so make those warnings more discreet.
diff --git a/engines/sword2/animation.h b/engines/sword2/animation.h
index b2a243b2ca..8669bdc8d8 100644
--- a/engines/sword2/animation.h
+++ b/engines/sword2/animation.h
@@ -40,7 +40,8 @@ namespace Sword2 {
enum DecoderType {
kVideoDecoderDXA = 0,
kVideoDecoderSMK = 1,
- kVideoDecoderPSX = 2
+ kVideoDecoderPSX = 2,
+ kVideoDecoderMP2 = 3
};
struct MovieText {
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