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 | |
| 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.
| -rw-r--r-- | engines/sword1/animation.cpp | 4 | ||||
| -rw-r--r-- | video/psx_decoder.cpp | 69 | ||||
| -rw-r--r-- | video/psx_decoder.h | 14 | 
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; | 
