aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/fmv
diff options
context:
space:
mode:
authorPaul Gilbert2010-09-01 07:35:38 +0000
committerEugene Sandulenko2010-10-12 23:23:10 +0000
commit3d3f1db15c50c9b675e29e0a10ee896fd8928445 (patch)
tree8ea732cc77df1b4cb7459d3aeef3fb0b250b4a02 /engines/sword25/fmv
parent579d872e96862882d4cf92e82a0e8deb82496020 (diff)
downloadscummvm-rg350-3d3f1db15c50c9b675e29e0a10ee896fd8928445.tar.gz
scummvm-rg350-3d3f1db15c50c9b675e29e0a10ee896fd8928445.tar.bz2
scummvm-rg350-3d3f1db15c50c9b675e29e0a10ee896fd8928445.zip
SWORD25: Merge of my pending changes to movie playback
svn-id: r53300
Diffstat (limited to 'engines/sword25/fmv')
-rw-r--r--engines/sword25/fmv/movieplayer.cpp98
-rw-r--r--engines/sword25/fmv/movieplayer.h17
-rw-r--r--engines/sword25/fmv/theora_decoder.cpp19
-rw-r--r--engines/sword25/fmv/theora_decoder.h1
4 files changed, 86 insertions, 49 deletions
diff --git a/engines/sword25/fmv/movieplayer.cpp b/engines/sword25/fmv/movieplayer.cpp
index f3504fcb8f..0475c9003e 100644
--- a/engines/sword25/fmv/movieplayer.cpp
+++ b/engines/sword25/fmv/movieplayer.cpp
@@ -32,100 +32,126 @@
*
*/
-#include "graphics/surface.h"
-
#include "sword25/fmv/movieplayer.h"
-#include "sword25/fmv/theora_decoder.h"
-#include "sword25/kernel/kernel.h"
#include "sword25/gfx/graphicengine.h"
+#include "sword25/gfx/panel.h"
+#include "sword25/kernel/kernel.h"
#include "sword25/package/packagemanager.h"
+#include "sword25/sfx/soundengine.h"
namespace Sword25 {
#define BS_LOG_PREFIX "MOVIEPLAYER"
+#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
+
Service *OggTheora_CreateObject(Kernel *pKernel) {
return new MoviePlayer(pKernel);
}
-MoviePlayer::MoviePlayer(Kernel *pKernel) : Service(pKernel) {
+MoviePlayer::MoviePlayer(Kernel *pKernel) : Service(pKernel),
+ _decoder(g_system->getMixer()) {
if (!_RegisterScriptBindings())
BS_LOG_ERRORLN("Script bindings could not be registered.");
else
BS_LOGLN("Script bindings registered.");
-
- _decoder = new TheoraDecoder();
- _backSurface = (static_cast<GraphicEngine *>(Kernel::GetInstance()->GetService("gfx")))->getSurface();
}
-bool MoviePlayer::LoadMovie(const Common::String &filename, unsigned int z) {
- Common::SeekableReadStream *in = Kernel::GetInstance()->GetPackage()->GetStream(filename);
+MoviePlayer::~MoviePlayer() {
+ _decoder.close();
+}
- if (!in) {
- BS_LOG_ERRORLN("Could not open movie file \"%s\".", filename.c_str());
+bool MoviePlayer::LoadMovie(const Common::String &Filename, unsigned int Z) {
+ // Get the file and load it into the decoder
+ uint dataSize;
+ const byte *data = reinterpret_cast<const byte *>(Kernel::GetInstance()->GetPackage()->GetFile(Filename, &dataSize));
+ Common::MemoryReadStream *stream = new Common::MemoryReadStream(
+ data, dataSize, DisposeAfterUse::YES);
+ _decoder.load(stream);
+
+ // Ausgabebitmap erstellen
+ GraphicEngine *pGfx = Kernel::GetInstance()->GetGfx();
+ _outputBitmap = pGfx->GetMainPanel()->AddDynamicBitmap(
+ _decoder.getWidth(), _decoder.getHeight());
+ if (!_outputBitmap.IsValid()) {
+ BS_LOG_ERRORLN("Output bitmap for movie playback could not be created.");
return false;
}
- debug(2, "LoadMovie(%s, %d)", filename.c_str(), z);
+ // Skalierung des Ausgabebitmaps berechnen, so dass es möglichst viel Bildschirmfläche einnimmt.
+ float ScreenToVideoWidth = (float) pGfx->GetDisplayWidth() / (float) _outputBitmap->GetWidth();
+ float ScreenToVideoHeight = (float) pGfx->GetDisplayHeight() / (float) _outputBitmap->GetHeight();
+ float ScaleFactor = MIN(ScreenToVideoWidth, ScreenToVideoHeight);
+ if (abs(ScaleFactor - 1.0f) < FLT_EPSILON) ScaleFactor = 1.0f;
+ _outputBitmap->SetScaleFactor(ScaleFactor);
- if (!_decoder->load(in)) {
- BS_LOG_ERRORLN("Could not load movie file \"%s\".", filename.c_str());
- return false;
- }
+ // Z-Wert setzen
+ _outputBitmap->SetZ(Z);
- warning("STUB: MoviePlayer::LoadMovie(). Z is not handled");
+ // Ausgabebitmap auf dem Bildschirm zentrieren
+ _outputBitmap->SetX((pGfx->GetDisplayWidth() - _outputBitmap->GetWidth()) / 2);
+ _outputBitmap->SetY((pGfx->GetDisplayHeight() - _outputBitmap->GetHeight()) / 2);
return true;
}
bool MoviePlayer::UnloadMovie() {
- _decoder->close();
+ _decoder.close();
+ _outputBitmap.Erase();
return true;
}
bool MoviePlayer::Play() {
- _decoder->pauseVideo(false);
-
+ _decoder.pauseVideo(false);
return true;
}
bool MoviePlayer::Pause() {
- _decoder->pauseVideo(true);
-
+ _decoder.pauseVideo(true);
return true;
}
void MoviePlayer::Update() {
- if (!_decoder->isVideoLoaded())
- return;
+ if (_decoder.isVideoLoaded()) {
+ Graphics::Surface *s = _decoder.decodeNextFrame();
- Graphics::Surface *surface = _decoder->decodeNextFrame();
-
- // Probably it's better to copy to _backSurface
- if (surface->w > 0 && surface->h > 0)
- g_system->copyRectToScreen((byte *)surface->getBasePtr(0, 0), surface->pitch, 0, 0,
- MIN(surface->w, _backSurface->w), MIN(surface->h, _backSurface->h));
+ // Transfer the next frame
+ assert(s->bytesPerPixel == 4);
+ byte *frameData = (byte *)s->getBasePtr(0, 0);
+ _outputBitmap->SetContent(frameData, s->pitch * s->h, 0, s->pitch);
+ }
}
bool MoviePlayer::IsMovieLoaded() {
- return _decoder->isVideoLoaded();
+ return _decoder.isVideoLoaded();
}
bool MoviePlayer::IsPaused() {
- return _decoder->isPaused();
+ return _decoder.isPaused();
}
float MoviePlayer::GetScaleFactor() {
- return 1.0f;
+ if (_decoder.isVideoLoaded())
+ return _outputBitmap->GetScaleFactorX();
+ else
+ return 0;
}
void MoviePlayer::SetScaleFactor(float ScaleFactor) {
+ if (_decoder.isVideoLoaded()) {
+ _outputBitmap->SetScaleFactor(ScaleFactor);
+
+ // Ausgabebitmap auf dem Bildschirm zentrieren
+ GraphicEngine *gfxPtr = Kernel::GetInstance()->GetGfx();
+ _outputBitmap->SetX((gfxPtr->GetDisplayWidth() - _outputBitmap->GetWidth()) / 2);
+ _outputBitmap->SetY((gfxPtr->GetDisplayHeight() - _outputBitmap->GetHeight()) / 2);
+ }
}
double MoviePlayer::GetTime() {
- return (double)_decoder->getElapsedTime() / 1000.0;
+ // FIXME: This may need conversion
+ return _decoder.getElapsedTime();
}
-
} // End of namespace Sword25
diff --git a/engines/sword25/fmv/movieplayer.h b/engines/sword25/fmv/movieplayer.h
index afca1eb808..cdbcf13f53 100644
--- a/engines/sword25/fmv/movieplayer.h
+++ b/engines/sword25/fmv/movieplayer.h
@@ -41,11 +41,14 @@
#include "sword25/kernel/common.h"
#include "sword25/kernel/service.h"
-#include "graphics/surface.h"
+#include "sword25/fmv/theora_decoder.h"
+#include "sword25/gfx/bitmap.h"
namespace Sword25 {
-class TheoraDecoder;
+// -----------------------------------------------------------------------------
+// Class definitions
+// -----------------------------------------------------------------------------
class MoviePlayer : public Service {
public:
@@ -54,10 +57,10 @@ public:
// -----------------------------------------------------------------------------
MoviePlayer(Kernel *pKernel);
- ~MoviePlayer() {};
+ ~MoviePlayer();
// -----------------------------------------------------------------------------
- // Abstract interface must be implemented by each Movie Player
+ // Player interface must be implemented by a Movie Player
// -----------------------------------------------------------------------------
/**
@@ -136,12 +139,12 @@ public:
* @remark This method can only be called when IsMovieLoaded() returns true.
*/
double GetTime();
-
private:
bool _RegisterScriptBindings();
- TheoraDecoder *_decoder;
- Graphics::Surface *_backSurface;
+ TheoraDecoder _decoder;
+
+ RenderObjectPtr<Bitmap> _outputBitmap;
};
} // End of namespace Sword25
diff --git a/engines/sword25/fmv/theora_decoder.cpp b/engines/sword25/fmv/theora_decoder.cpp
index bc95e10678..cbd60d9fdd 100644
--- a/engines/sword25/fmv/theora_decoder.cpp
+++ b/engines/sword25/fmv/theora_decoder.cpp
@@ -53,15 +53,18 @@ TheoraDecoder::TheoraDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundT
_fileStream = 0;
_surface = 0;
+ _theoraPacket = 0;
+ _vorbisPacket = 0;
+ _theoraSetup = 0;
+ _stateFlag = false;
+
_soundType = soundType;
_audStream = 0;
_audHandle = new Audio::SoundHandle();
- _theoraDecode = 0;
- _theoraSetup = 0;
+ ogg_sync_init(&_oggSync);
_curFrame = 0;
-
_audiobuf = (ogg_int16_t *)calloc(AUDIOFD_FRAGSIZE, sizeof(ogg_int16_t));
reset();
@@ -69,6 +72,7 @@ TheoraDecoder::TheoraDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundT
TheoraDecoder::~TheoraDecoder() {
close();
+ delete _fileStream;
delete _audHandle;
free(_audiobuf);
}
@@ -249,14 +253,12 @@ bool TheoraDecoder::load(Common::SeekableReadStream *stream) {
_ppLevel = _ppLevelMax;
th_decode_ctl(_theoraDecode, TH_DECCTL_SET_PPLEVEL, &_ppLevel, sizeof(_ppLevel));
_ppInc = 0;
-
} else {
// tear down the partial theora setup
th_info_clear(&_theoraInfo);
th_comment_clear(&_theoraComment);
}
-
th_setup_free(_theoraSetup);
_theoraSetup = 0;
@@ -279,6 +281,7 @@ bool TheoraDecoder::load(Common::SeekableReadStream *stream) {
}
_surface = new Graphics::Surface();
+
_surface->create(_theoraInfo.frame_width, _theoraInfo.frame_height, 4);
return true;
@@ -295,6 +298,7 @@ void TheoraDecoder::close() {
if (_mixer)
_mixer->stopHandle(*_audHandle);
_audStream = 0;
+ _vorbisPacket = false;
}
if (_theoraPacket) {
ogg_stream_clear(&_theoraOut);
@@ -302,6 +306,7 @@ void TheoraDecoder::close() {
th_comment_clear(&_theoraComment);
th_info_clear(&_theoraInfo);
_theoraDecode = 0;
+ _theoraPacket = false;
}
if (!_fileStream)
@@ -322,7 +327,7 @@ void TheoraDecoder::close() {
Graphics::Surface *TheoraDecoder::decodeNextFrame() {
int i, j;
- _stateFlag = false; // playback has not begun
+// _stateFlag = false; // playback has not begun
// we want a video and audio frame ready to go at all times. If
// we have to buffer incoming, buffer the compressed data (ie, let
@@ -404,9 +409,11 @@ Graphics::Surface *TheoraDecoder::decodeNextFrame() {
}
// If playback has begun, top audio buffer off immediately.
+/* FIXME: This is currently crashing
if (_stateFlag) {
_audStream->queueBuffer((byte *)_audiobuf, AUDIOFD_FRAGSIZE, DisposeAfterUse::NO, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO);
}
+*/
// are we at or past time for this video frame?
if (_stateFlag && _videobufReady) {
diff --git a/engines/sword25/fmv/theora_decoder.h b/engines/sword25/fmv/theora_decoder.h
index 3ce53e0900..12d8035c0a 100644
--- a/engines/sword25/fmv/theora_decoder.h
+++ b/engines/sword25/fmv/theora_decoder.h
@@ -82,6 +82,7 @@ public:
// It is not possible to get frame count easily
// I.e. seeking is required
assert(0);
+ return 0;
}
Graphics::PixelFormat getPixelFormat() const {
return Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);