diff options
author | Matthew Hoops | 2012-01-10 22:15:04 -0500 |
---|---|---|
committer | Willem Jan Palenstijn | 2012-02-23 22:48:18 +0100 |
commit | 66cd8bdd68d9e0d14e40c9f55c06f8ea9cf2006b (patch) | |
tree | 37ee982ed7b485704bdfc0176d228bbeb5f522f1 /video | |
parent | ee35d32a362d58891fedff9843867397f2d4497b (diff) | |
download | scummvm-rg350-66cd8bdd68d9e0d14e40c9f55c06f8ea9cf2006b.tar.gz scummvm-rg350-66cd8bdd68d9e0d14e40c9f55c06f8ea9cf2006b.tar.bz2 scummvm-rg350-66cd8bdd68d9e0d14e40c9f55c06f8ea9cf2006b.zip |
VIDEO: Make PSX streams calculate frame timing solely from CD speed
BS2 videos now play at the proper rate and BS1 videos have improved a/v sync.
Diffstat (limited to 'video')
-rw-r--r-- | video/psx_decoder.cpp | 69 | ||||
-rw-r--r-- | video/psx_decoder.h | 14 |
2 files changed, 38 insertions, 45 deletions
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; |