aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sword1/animation.cpp4
-rw-r--r--video/psx_decoder.cpp69
-rw-r--r--video/psx_decoder.h14
3 files changed, 40 insertions, 47 deletions
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 9e190e01d0..a1ace0f331 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -410,8 +410,8 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *
if (Common::File::exists(filename)) {
#ifdef USE_RGB_COLOR
- // All BS1 PSX videos seem to be 15fps
- Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(15);
+ // All BS1 PSX videos run the videos at 2x speed
+ Video::VideoDecoder *psxDecoder = new Video::PSXStreamDecoder(Video::PSXStreamDecoder::kCD2x);
return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, psxDecoder, kVideoDecoderPSX);
#else
GUI::MessageDialog dialog(Common::String::format(_("PSX stream cutscene '%s' cannot be played in paletted mode"), filename.c_str()), _("OK"));
diff --git a/video/psx_decoder.cpp b/video/psx_decoder.cpp
index a0705e8804..7c04b7f041 100644
--- a/video/psx_decoder.cpp
+++ b/video/psx_decoder.cpp
@@ -38,31 +38,6 @@
namespace Video {
-PSXStreamDecoder::PSXStreamDecoder(Common::Rational frameRate) {
- assert(frameRate != 0);
- initCommon();
- _frameRate = frameRate;
- _frameCount = 0;
- _speed = kCDUnk;
-}
-
-PSXStreamDecoder::PSXStreamDecoder(CDSpeed speed, uint32 frameCount) {
- assert(speed != kCDUnk);
- assert(frameCount != 0);
- initCommon();
- _frameCount = frameCount;
- _speed = speed;
- // frame rate will be calculated in loadStream()
-}
-
-PSXStreamDecoder::~PSXStreamDecoder() {
- close();
- delete _surface;
- delete _acHuffman;
- delete _dcHuffmanLuma;
- delete _dcHuffmanChroma;
-}
-
// Here are the codes/lengths/symbols that are used for decoding
// DC coefficients (version 3 frames only)
@@ -174,7 +149,7 @@ static const uint32 s_huffmanACSymbols[AC_CODE_COUNT] = {
END_OF_BLOCK
};
-void PSXStreamDecoder::initCommon() {
+PSXStreamDecoder::PSXStreamDecoder(CDSpeed speed, uint32 frameCount) : _nextFrameStartTime(0, speed), _frameCount(frameCount) {
_stream = 0;
_audStream = 0;
_surface = new Graphics::Surface();
@@ -184,6 +159,14 @@ void PSXStreamDecoder::initCommon() {
_dcHuffmanLuma = new Common::Huffman(0, DC_CODE_COUNT, s_huffmanDCLumaCodes, s_huffmanDCLumaLengths, s_huffmanDCSymbols);
}
+PSXStreamDecoder::~PSXStreamDecoder() {
+ close();
+ delete _surface;
+ delete _acHuffman;
+ delete _dcHuffmanLuma;
+ delete _dcHuffmanChroma;
+}
+
#define RAW_CD_SECTOR_SIZE 2352
#define CDXA_TYPE_MASK 0x0E
@@ -227,14 +210,6 @@ bool PSXStreamDecoder::loadStream(Common::SeekableReadStream *stream) {
delete sector;
_stream->seek(0);
- // Calculate frame rate based on CD speed
- if (_speed != kCDUnk) {
- // TODO: This algorithm is too basic and not accurate enough
- // TODO: Count the number of sectors per frame to get a better estimate
- _frameRate = Common::Rational(_speed * _frameCount, _stream->size() / RAW_CD_SECTOR_SIZE);
- _frameRate.debugPrint(0, "Approximate PSX Stream Frame Rate:");
- }
-
return true;
}
@@ -267,7 +242,20 @@ uint32 PSXStreamDecoder::getElapsedTime() const {
//if (_audStream)
// return _mixer->getSoundElapsedTime(_audHandle);
- return FixedRateVideoDecoder::getElapsedTime();
+ return VideoDecoder::getElapsedTime();
+}
+
+uint32 PSXStreamDecoder::getTimeToNextFrame() const {
+ if (!isVideoLoaded() || endOfVideo())
+ return 0;
+
+ uint32 nextTimeMillis = _nextFrameStartTime.msecs();
+ uint32 elapsedTime = getElapsedTime();
+
+ if (elapsedTime > nextTimeMillis)
+ return 0;
+
+ return nextTimeMillis - elapsedTime;
}
#define VIDEO_DATA_CHUNK_SIZE 2016
@@ -276,9 +264,11 @@ uint32 PSXStreamDecoder::getElapsedTime() const {
const Graphics::Surface *PSXStreamDecoder::decodeNextFrame() {
Common::SeekableReadStream *sector = 0;
byte *partialFrame = 0;
+ int sectorsRead = 0;
while (!endOfVideo()) {
sector = readSector();
+ sectorsRead++;
if (!sector)
error("Corrupt PSX stream sector");
@@ -322,6 +312,15 @@ const Graphics::Surface *PSXStreamDecoder::decodeNextFrame() {
if (_curFrame == 0)
_startTime = g_system->getMillis();
+ // Increase the time by the amount of sectors we read
+ // One may notice that this is still not the most precise
+ // method since a frame takes up the time its sectors took
+ // up instead of the amount of time it takes the next frame
+ // to be read from the sectors. The actual frame rate should
+ // be constant instead of variable, so the slight difference
+ // in a frame's showing time is negligible (1/150 of a second).
+ _nextFrameStartTime = _nextFrameStartTime.addFrames(sectorsRead);
+
return _surface;
}
} else
diff --git a/video/psx_decoder.h b/video/psx_decoder.h
index 4223f0344e..621870448b 100644
--- a/video/psx_decoder.h
+++ b/video/psx_decoder.h
@@ -53,18 +53,16 @@ namespace Video {
* - sword1 (psx)
* - sword2 (psx)
*/
-class PSXStreamDecoder : public FixedRateVideoDecoder {
+class PSXStreamDecoder : public VideoDecoder {
public:
// CD speed in sectors/second
// Calling code should use these enum values instead of the constants
enum CDSpeed {
- kCDUnk = 0,
kCD1x = 75,
kCD2x = 150
};
- PSXStreamDecoder(Common::Rational frameRate);
- PSXStreamDecoder(CDSpeed speed, uint32 frameCount);
+ PSXStreamDecoder(CDSpeed speed, uint32 frameCount = 0);
virtual ~PSXStreamDecoder();
bool loadStream(Common::SeekableReadStream *stream);
@@ -75,22 +73,18 @@ public:
uint16 getHeight() const { return _surface->h; }
uint32 getFrameCount() const { return _frameCount; }
uint32 getElapsedTime() const;
+ uint32 getTimeToNextFrame() const;
const Graphics::Surface *decodeNextFrame();
Graphics::PixelFormat getPixelFormat() const { return _surface->format; }
bool endOfVideo() const { return _stream->pos() >= _stream->size(); }
-protected:
- // Hardcoded frame rate
- Common::Rational getFrameRate() const { return _frameRate; }
-
private:
void initCommon();
Common::SeekableReadStream *_stream;
Graphics::Surface *_surface;
- CDSpeed _speed;
uint32 _frameCount;
- Common::Rational _frameRate;
+ Audio::Timestamp _nextFrameStartTime;
Audio::SoundHandle _audHandle;
Audio::QueuingAudioStream *_audStream;