void MoviePlayer::handleNextFrame() {
	if (!isVideoLoaded())
		return;

	VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];

	if (_flags & 2) {
		uint8 *dstPtr = _vm->getResourceAddress(rtImage, _wizResNum);
		assert(dstPtr);
		uint8 *dst = _vm->findWrappedBlock(MKID_BE('WIZD'), dstPtr, 0, 0);
		assert(dst);
		copyFrameToBuffer(dst, kDstResource, 0, 0, _vm->_screenWidth * _vm->_bytesPerPixel);
	} else if (_flags & 1) {
		copyFrameToBuffer(pvs->getBackPixels(0, 0), kDstScreen, 0, 0, pvs->pitch);

		Common::Rect imageRect(getWidth(), getHeight());
		_vm->restoreBackgroundHE(imageRect);
	} else {
		copyFrameToBuffer(pvs->getPixels(0, 0), kDstScreen, 0, 0, pvs->pitch);

		Common::Rect imageRect(getWidth(), getHeight());
		_vm->markRectAsDirty(kMainVirtScreen, imageRect);
	}

	if (endOfVideo())
		close();
}
Exemple #2
0
void MoviePlayerSMK::nextFrame() {
	if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo())
		rewind();

	if (!endOfVideo()) {
		decodeNextFrame();
		if (_vm->_interactiveVideo == TYPE_OMNITV) {
			copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth);
		} else if (_vm->_interactiveVideo == TYPE_LOOPING) {
			copyFrameToBuffer(_vm->getBackBuf(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
		}
	} else if (_vm->_interactiveVideo == TYPE_OMNITV) {
		close();
		_vm->_interactiveVideo = 0;
		_vm->_variableArray[254] = 6747;
	}
}
Exemple #3
0
void MoviePlayerDXA::playVideo() {
	// Most of the videos included in the Amiga version, reduced the
	// resoluton to 384 x 280, so require the screen to be cleared,
	// before starting playing those videos.
	if (getWidth() == 384 && getHeight() == 280) {
		_vm->clearSurfaces();
	}

	while (!endOfVideo() && !_skipMovie && !_vm->shouldQuit())
		handleNextFrame();
}
Exemple #4
0
void RivenVideo::playBlocking(int32 endTime) {
	_vm->_cursor->hideCursor();

	if (!_playing) {
		play();
	}

	// Sanity check
	if (isLooping())
		error("Called playBlocking() on a looping video");

	bool playTillEnd;
	if (endTime == -1) {
		playTillEnd = true;
	} else {
		playTillEnd = false;
		_video->setEndTime(Audio::Timestamp(0, endTime, 600));
	}

	if (playTillEnd) {
		enable();
	}

	bool continuePlaying = true;
	while (!endOfVideo() && !_vm->hasGameEnded() && continuePlaying) {
		// Draw a frame
		_vm->doFrame();

		// Handle skipping
		if (playTillEnd && _vm->getStack()->keyGetAction() == kKeyActionSkip) {
			continuePlaying = false;

			// Seek to the last frame
			_video->seek(_video->getDuration().addMsecs(-1));

			_vm->getStack()->mouseForceUp();
			_vm->getStack()->keyResetAction();
		}
	}

	if (playTillEnd) {
		disable();
		stop();
	}

	// Execute the stored opcode
	uint16 storedOpcodeMovieSlot = _vm->_scriptMan->getStoredMovieOpcodeSlot();
	uint32 storedOpcodeTime = _vm->_scriptMan->getStoredMovieOpcodeTime();
	if (_slot == storedOpcodeMovieSlot && getTime() >= storedOpcodeTime) { // CHECKME: Suspicious use of time units
		_vm->_scriptMan->runStoredMovieOpcode();
	}

	_vm->_cursor->showCursor();
}
Exemple #5
0
uint32 QuickTimeDecoder::getTimeToNextFrame() const {
	if (endOfVideo() || _curFrame < 0)
		return 0;

	// Convert from the QuickTime rate base to 1000
	uint32 nextFrameStartTime = _nextFrameStartTime * 1000 / _streams[_videoStreamIndex]->time_scale;
	uint32 elapsedTime = getElapsedTime();

	if (nextFrameStartTime <= elapsedTime)
		return 0;

	return nextFrameStartTime - elapsedTime;
}
Exemple #6
0
void MoviePlayerDXA::nextFrame() {
	if (_bgSoundStream && _vm->_mixer->isSoundHandleActive(_bgSound) && needsUpdate()) {
		copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth);
		return;
	}

	if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo()) {
		rewind();
		startSound();
	}

	if (!endOfVideo()) {
		if (_vm->_interactiveVideo == TYPE_OMNITV) {
			copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth);
		} else if (_vm->_interactiveVideo == TYPE_LOOPING) {
			copyFrameToBuffer(_vm->getBackBuf(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
		}
	} else if (_vm->_interactiveVideo == TYPE_OMNITV) {
		close();
		_vm->_interactiveVideo = 0;
		_vm->_variableArray[254] = 6747;
	}
}
Exemple #7
0
uint32 FixedRateVideoDecoder::getTimeToNextFrame() const {
	if (endOfVideo() || _curFrame < 0)
		return 0;

	uint32 elapsedTime = getTime();
	uint32 nextFrameStartTime = getFrameBeginTime(_curFrame + 1);

	// If the time that the next frame should be shown has past
	// the frame should be shown ASAP.
	if (nextFrameStartTime <= elapsedTime)
		return 0;

	return nextFrameStartTime - elapsedTime;
}
uint32 VideoDecoder::getTimeToNextFrame() const {
	if (endOfVideo() || _needsUpdate)
		return 0;

	const VideoTrack *track = findNextVideoTrack();

	if (!track)
		return 0;

	uint32 elapsedTime = getTime();
	uint32 nextFrameStartTime = track->getNextFrameStartTime();

	if (nextFrameStartTime <= elapsedTime)
		return 0;

	return nextFrameStartTime - elapsedTime;
}
Exemple #9
0
void SeekableBinkDecoder::skipNextFrame() {
	if (endOfVideo())
		return;

	VideoFrame &frame = _frames[_curFrame + 1];

	if (!_bink->seek(frame.offset))
		error("Bad bink seek");

	uint32 frameSize = frame.size;

	for (uint32 i = 0; i < _audioTracks.size(); i++) {
		uint32 audioPacketLength = _bink->readUint32LE();

		frameSize -= 4;

		if (frameSize < audioPacketLength)
			error("Audio packet too big for the frame");

		if (audioPacketLength >= 4) {
			// Skip audio data
			_bink->seek(audioPacketLength, SEEK_CUR);

			frameSize -= audioPacketLength;
		}
	}

	uint32 videoPacketStart = _bink->pos();
	uint32 videoPacketEnd   = _bink->pos() + frameSize;

	frame.bits =
		new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink,
		    videoPacketStart, videoPacketEnd), true);

	videoPacket(frame);

	delete frame.bits;
	frame.bits = 0;

	_curFrame++;
	if (_curFrame == 0)
		_startTime = g_system->getMillis();
}
Exemple #10
0
uint32 VideoDecoder::getTimeToNextFrame() const {
	if (endOfVideo() || _needsUpdate || !_nextVideoTrack)
		return 0;

	uint32 currentTime = getTime();
	uint32 nextFrameStartTime = _nextVideoTrack->getNextFrameStartTime();

	if (_nextVideoTrack->isReversed()) {
		// For reversed videos, we need to handle the time difference the opposite way.
		if (nextFrameStartTime >= currentTime)
			return 0;

		return currentTime - nextFrameStartTime;
	}

	// Otherwise, handle it normally.
	if (nextFrameStartTime <= currentTime)
		return 0;

	return nextFrameStartTime - currentTime;
}
Exemple #11
0
void MoviePlayerSMK::playVideo() {
	while (!endOfVideo() && !_skipMovie && !_vm->shouldQuit())
		handleNextFrame();
}
Exemple #12
0
const Graphics::Surface *BinkDecoder::decodeNextFrame() {
	if (endOfVideo())
		return 0;

	VideoFrame &frame = _frames[_curFrame + 1];

	if (!_bink->seek(frame.offset))
		error("Bad bink seek");

	uint32 frameSize = frame.size;

	for (uint32 i = 0; i < _audioTracks.size(); i++) {
		AudioTrack &audio = _audioTracks[i];

		uint32 audioPacketLength = _bink->readUint32LE();

		frameSize -= 4;

		if (frameSize < audioPacketLength)
			error("Audio packet too big for the frame");

		if (audioPacketLength >= 4) {
			uint32 audioPacketStart = _bink->pos();
			uint32 audioPacketEnd   = _bink->pos() + audioPacketLength;

			if (i == _audioTrack) {
				// Only play one audio track

				//                  Number of samples in bytes
				audio.sampleCount = _bink->readUint32LE() / (2 * audio.channels);

				audio.bits =
					new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink,
					    audioPacketStart + 4, audioPacketEnd), true);

				audioPacket(audio);

				delete audio.bits;
				audio.bits = 0;
			}

			_bink->seek(audioPacketEnd);

			frameSize -= audioPacketLength;
		}
	}

	uint32 videoPacketStart = _bink->pos();
	uint32 videoPacketEnd   = _bink->pos() + frameSize;

	frame.bits =
		new Common::BitStream32LELSB(new Common::SeekableSubReadStream(_bink,
		    videoPacketStart, videoPacketEnd), true);

	videoPacket(frame);

	delete frame.bits;
	frame.bits = 0;

	_curFrame++;
	if (_curFrame == 0)
		_startTime = g_system->getMillis();

	return &_surface;
}
Exemple #13
0
const Graphics::Surface *BinkDecoder::decodeNextFrame() {
	if (endOfVideo())
		return 0;

	VideoFrame &frame = _frames[_curFrame + 1];

	if (!_bink->seek(frame.offset))
		error("Bad bink seek");

	uint32 frameSize = frame.size;

	for (uint32 i = 0; i < _audioTracks.size(); i++) {
		AudioTrack &audio = _audioTracks[i];

		uint32 audioPacketLength = _bink->readUint32LE();

		frameSize -= 4;

		if (frameSize < audioPacketLength)
			error("Audio packet too big for the frame");

		if (audioPacketLength >= 4) {
			if (i == _audioTrack) {
				// Only play one audio track

				//                  Number of samples in bytes
				audio.sampleCount = _bink->readUint32LE() / (2 * audio.channels);

				audio.bits = new Common::BitStream32LE(*_bink, (audioPacketLength - 4) * 8);

				audioPacket(audio);

				delete audio.bits;
				audio.bits = 0;

			} else
				// Skip the rest
				_bink->skip(audioPacketLength);

			frameSize -= audioPacketLength;
		}
	}

	frame.bits = new Common::BitStream32LE(*_bink, frameSize * 8);

	videoPacket(frame);

	delete frame.bits;
	frame.bits = 0;

	_curFrame++;
	if (_curFrame == 0)
		_startTime = g_system->getMillis();

	if (!_audioStarted && _audioStream) {
		_audioStarted = true;
		g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audioHandle, _audioStream);
	}

	return &_surface;
}
Exemple #14
0
bool VideoDecoder::needsUpdate() const {
	return !endOfVideo() && getTimeToNextFrame() == 0;
}
Exemple #15
0
void SmushDecoder::handleFrame() {
	uint32 tag;
	int32 size;
	int pos = 0;

	if (_videoLooping && _curFrame == _nbframes - 1) {
		_file->seek(_startPos, SEEK_SET);
		_curFrame = -1;
	}

	if (_curFrame == -1)
		_startTime = g_system->getMillis();

	if (_videoPause)
		return;

	if (endOfVideo()) { // Looping is handled outside, by rewinding the video.
		_videoPause = true;
		return;
	}

	tag = _file->readUint32BE();
	if (tag == MKTAG('A','N','N','O')) {
		char *anno;
		byte *data;

		size = _file->readUint32BE();
		data = new byte[size];
		_file->read(data, size);
		anno = (char *)data;
		if (strncmp(anno, ANNO_HEADER, sizeof(ANNO_HEADER) - 1) == 0) {
			//char *annoData = anno + sizeof(ANNO_HEADER);

			// Examples:
			//  Water streaming around boat from Manny's balcony
			//  MakeAnim animation type 'Bl16' parameters: 10000;12000;100;1;0;0;0;0;25;0;
			//  Water in front of the Blue Casket
			//  MakeAnim animation type 'Bl16' parameters: 20000;25000;100;1;0;0;0;0;25;0;
			//  Scrimshaw exterior:
			//  MakeAnim animation type 'Bl16' parameters: 6000;8000;100;0;0;0;0;0;2;0;
			//  Lola engine room (loops a limited number of times?):
			//  MakeAnim animation type 'Bl16' parameters: 6000;8000;90;1;0;0;0;0;2;0;
			Debug::debug(Debug::Movie, "Announcement data: %s\n", anno);
			// It looks like the announcement data is actually for setting some of the
			// header parameters, not for any looping purpose
		} else {
			Debug::debug(Debug::Movie, "Announcement header not understood: %s\n", anno);
		}
		delete[] anno;
		tag = _file->readUint32BE();
	}

	assert(tag == MKTAG('F','R','M','E'));
	size = _file->readUint32BE();
	byte *frame = new byte[size];
	_file->read(frame, size);

	do {
		if (READ_BE_UINT32(frame + pos) == MKTAG('B','l','1','6')) {
			_blocky16->decode((byte *)_surface.pixels, frame + pos + 8);
			pos += READ_BE_UINT32(frame + pos + 4) + 8;
		} else if (READ_BE_UINT32(frame + pos) == MKTAG('W','a','v','e')) {
			int decompressed_size = READ_BE_UINT32(frame + pos + 8);
			if (decompressed_size < 0)
				handleWave(frame + pos + 8 + 4 + 8, READ_BE_UINT32(frame + pos + 8 + 8));
			else
				handleWave(frame + pos + 8 + 4, decompressed_size);
			pos += READ_BE_UINT32(frame + pos + 4) + 8;
		} else {
			Debug::error(Debug::Movie, "SmushDecoder::handleFrame() unknown tag");
		}
	} while (pos < size);
	delete[] frame;

	++_curFrame;
}